diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ApplicationTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ApplicationTest.java index eb5e2b8c1e9ca6078f059d2b21320526e24fc25f..ef4e65365cfc49e760bbe21232be7ec383ac68e2 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ApplicationTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ApplicationTest.java @@ -12,7 +12,7 @@ package org.openhab.habdroid; import android.app.Application; import android.test.ApplicationTestCase; -/** +/* * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> */ public class ApplicationTest extends ApplicationTestCase<Application> { diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/FragmentStatusIdlingResource.java b/mobile/src/androidTest/java/org/openhab/habdroid/FragmentStatusIdlingResource.java index 0f8925a10f1894edb4b5526b04bd86e15984174d..249132d3be6596ebbf713f8af6d0315ab1020232 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/FragmentStatusIdlingResource.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/FragmentStatusIdlingResource.java @@ -5,9 +5,8 @@ import android.support.test.espresso.IdlingResource; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import org.openhab.habdroid.ui.OpenHABWidgetListFragment; +import org.openhab.habdroid.ui.WidgetListFragment; import org.openhab.habdroid.ui.activity.ContentController; -import org.openhab.habdroid.ui.activity.PageConnectionHolderFragment; public class FragmentStatusIdlingResource implements IdlingResource { private final String mName; @@ -43,8 +42,8 @@ public class FragmentStatusIdlingResource implements IdlingResource { if (f instanceof ContentController.ProgressFragment) { return true; } - if (f instanceof OpenHABWidgetListFragment) { - if (((OpenHABWidgetListFragment) f).mRecyclerView.hasPendingAdapterUpdates()) { + if (f instanceof WidgetListFragment) { + if (((WidgetListFragment) f).mRecyclerView.hasPendingAdapterUpdates()) { return true; } } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/OpenHABProgressbarIdlingResource.java b/mobile/src/androidTest/java/org/openhab/habdroid/OpenHABProgressbarIdlingResource.java deleted file mode 100644 index bff80e36129bde8ef6c3a26f418ae29393458db6..0000000000000000000000000000000000000000 --- a/mobile/src/androidTest/java/org/openhab/habdroid/OpenHABProgressbarIdlingResource.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.openhab.habdroid; - -import android.support.annotation.NonNull; -import android.support.test.espresso.IdlingResource; -import android.view.View; - -public class OpenHABProgressbarIdlingResource implements IdlingResource { - private String name; - private View progressBar; - private ResourceCallback callback; - - public OpenHABProgressbarIdlingResource(@NonNull String name, @NonNull View progressBar) { - this.name = name; - this.progressBar = progressBar; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public boolean isIdleNow() { - boolean idle = progressBar.getVisibility() == View.INVISIBLE; - if (idle && callback != null) - callback.onTransitionToIdle(); - - return idle; - } - - @Override - public void registerIdleTransitionCallback(ResourceCallback callback) { - this.callback = callback; - } -} diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarAwareTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarAwareTest.java index 5a7a344907fd358faeb4b9ac382b05d3fb300c5a..6fb0d1308dcd75b3e351f15906d1b0088abd93b2 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarAwareTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarAwareTest.java @@ -3,23 +3,17 @@ package org.openhab.habdroid; import android.support.test.espresso.IdlingRegistry; import android.support.test.espresso.IdlingResource; import android.support.test.espresso.intent.rule.IntentsTestRule; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; import android.view.View; import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.openhab.habdroid.ui.OpenHABMainActivity; -import org.openhab.habdroid.ui.OpenHABWidgetListFragment; -import org.openhab.habdroid.ui.activity.ContentController; -import org.openhab.habdroid.ui.activity.PageConnectionHolderFragment; +import org.openhab.habdroid.ui.MainActivity; public abstract class ProgressbarAwareTest { - @Rule - public IntentsTestRule<OpenHABMainActivity> mActivityTestRule = new IntentsTestRule<> - (OpenHABMainActivity.class, true, false); + public IntentsTestRule<MainActivity> mActivityTestRule = + new IntentsTestRule<>(MainActivity.class, true, false); private IdlingResource mProgressbarIdlingResource; private IdlingResource mFragmentIdlingResource; @@ -36,9 +30,10 @@ public abstract class ProgressbarAwareTest { protected IdlingResource getProgressbarIdlingResource() { if (mProgressbarIdlingResource == null) { - View progressBar = mActivityTestRule.getActivity().findViewById(R.id.toolbar_progress_bar); - mProgressbarIdlingResource = new OpenHABProgressbarIdlingResource("Progressbar " + - "IdleResource", progressBar); + final View progressBar = + mActivityTestRule.getActivity().findViewById(R.id.toolbar_progress_bar); + mProgressbarIdlingResource = + new ProgressbarIdlingResource("Progressbar IdleResource", progressBar); } return mProgressbarIdlingResource; } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarIdlingResource.java b/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarIdlingResource.java new file mode 100644 index 0000000000000000000000000000000000000000..1e8a88745e52f9f889230a35a196a7037a34206e --- /dev/null +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ProgressbarIdlingResource.java @@ -0,0 +1,36 @@ +package org.openhab.habdroid; + +import android.support.annotation.NonNull; +import android.support.test.espresso.IdlingResource; +import android.view.View; + +public class ProgressbarIdlingResource implements IdlingResource { + private String mName; + private View mProgressBar; + private ResourceCallback mCallback; + + public ProgressbarIdlingResource(@NonNull String name, @NonNull View progressBar) { + mName = name; + mProgressBar = progressBar; + } + + @Override + public String getName() { + return mName; + } + + @Override + public boolean isIdleNow() { + boolean idle = mProgressBar.getVisibility() == View.INVISIBLE; + if (idle && mCallback != null) { + mCallback.onTransitionToIdle(); + } + + return idle; + } + + @Override + public void registerIdleTransitionCallback(ResourceCallback callback) { + mCallback = callback; + } +} diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/TestWithIntro.java b/mobile/src/androidTest/java/org/openhab/habdroid/TestWithIntro.java index 8351bf657885db6161bd80cfea886cae42c999af..30a7103e7094fa4132dd832d4c82ddd329f1038b 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/TestWithIntro.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/TestWithIntro.java @@ -6,7 +6,6 @@ import android.support.test.InstrumentationRegistry; import org.openhab.habdroid.util.Constants; public abstract class TestWithIntro extends ProgressbarAwareTest { - @Override public void setup() { PreferenceManager diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/screengrab/ScreengrabTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/screengrab/ScreengrabTest.java index edb5425894db36d36d4a384fb726b71adeaa43b1..002b944515532941ce8eef3d84a007445f420b38 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/screengrab/ScreengrabTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/screengrab/ScreengrabTest.java @@ -1,47 +1,23 @@ package org.openhab.habdroid.screengrab; -import android.support.annotation.IdRes; -import android.support.test.espresso.DataInteraction; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; import android.support.test.espresso.ViewInteraction; import android.support.test.espresso.contrib.RecyclerViewActions; -import android.support.test.espresso.matcher.BoundedMatcher; import android.support.test.runner.AndroidJUnit4; -import android.support.v7.widget.RecyclerView; import android.test.suitebuilder.annotation.LargeTest; -import android.view.View; -import org.hamcrest.Description; -import org.hamcrest.Matcher; import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; -import org.openhab.habdroid.BuildConfig; import org.openhab.habdroid.R; import org.openhab.habdroid.TestWithoutIntro; -import org.openhab.habdroid.ui.BasicWidgetTest; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; import tools.fastlane.screengrab.locale.LocaleTestRule; -import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.Espresso.pressBack; import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.longClick; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withClassName; import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.anything; -import static org.hamcrest.Matchers.is; -import static org.openhab.habdroid.ui.BasicWidgetTest.atPositionOnView; -import static org.openhab.habdroid.ui.BasicWidgetTest.onChildView; -import static tools.fastlane.screengrab.Screengrab.*; +import static tools.fastlane.screengrab.Screengrab.screenshot; @LargeTest @RunWith(AndroidJUnit4.class) diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ui/BasicWidgetTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ui/BasicWidgetTest.java index 8d6c93d5190218c8aac5a3e6cde390c56e0a518c..1d3086c65209f006ccdac8dd47efebf6bdb29025 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ui/BasicWidgetTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ui/BasicWidgetTest.java @@ -1,6 +1,5 @@ package org.openhab.habdroid.ui; - import android.support.annotation.IdRes; import android.support.test.espresso.DataInteraction; import android.support.test.espresso.UiController; @@ -15,8 +14,6 @@ import android.view.View; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.openhab.habdroid.BuildConfig; @@ -27,6 +24,8 @@ import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; +import static android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withClassName; import static android.support.test.espresso.matcher.ViewMatchers.withId; @@ -38,35 +37,36 @@ import static org.hamcrest.Matchers.is; @RunWith(AndroidJUnit4.class) public class BasicWidgetTest extends TestWithoutIntro { @Test - public void openHABMainActivityTest() throws InterruptedException { + public void mainActivityTest() { ViewInteraction recyclerView = onView(withId(R.id.recyclerview)); recyclerView - .perform(RecyclerViewActions.scrollToPosition(0)) + .perform(scrollToPosition(0)) .check(matches(atPositionOnView(0, isDisplayed(), R.id.widgetlabel))) .check(matches(atPositionOnView(0, withText("First Floor"), R.id.widgetlabel))); recyclerView - .perform(RecyclerViewActions.scrollToPosition(6)) + .perform(scrollToPosition(6)) .check(matches(atPositionOnView(6, isDisplayed(), R.id.widgetlabel))) - .check(matches(atPositionOnView(6, withText("Astronomical Data"), R.id.widgetlabel))); + .check(matches( + atPositionOnView(6, withText("Astronomical Data"), R.id.widgetlabel))); // does it show "garden"? recyclerView - .perform(RecyclerViewActions.scrollToPosition(3)) + .perform(scrollToPosition(3)) .check(matches(atPositionOnView(3, isDisplayed(), R.id.widgetlabel))) .check(matches(atPositionOnView(3, withText("Garden"), R.id.widgetlabel))); // open widget overview recyclerView - .perform(RecyclerViewActions.actionOnItemAtPosition(10, click())); + .perform(actionOnItemAtPosition(10, click())); // check whether selection widget appears and click on it recyclerView - .perform(RecyclerViewActions.scrollToPosition(4)) + .perform(scrollToPosition(4)) .check(matches(atPositionOnView(4, withText("Scene Selection"), R.id.widgetlabel))) .check(matches(atPositionOnView(4, isDisplayed(), R.id.spinner))) - .perform(RecyclerViewActions.actionOnItemAtPosition(4, onChildView(click(), R.id.spinner))); + .perform(actionOnItemAtPosition(4, onChildView(click(), R.id.spinner))); DataInteraction appCompatCheckedTextView = onData(anything()) .inAdapterView(withClassName( @@ -77,33 +77,33 @@ public class BasicWidgetTest extends TestWithoutIntro { // check whether scene radio button group is present recyclerView - .perform(RecyclerViewActions.scrollToPosition(5)) + .perform(scrollToPosition(5)) .check(matches(atPositionOnView(5, isDisplayed(), R.id.switchgroup))); // check whether switch is displayed recyclerView - .perform(RecyclerViewActions.scrollToPosition(1)) + .perform(scrollToPosition(1)) .check(matches(atPositionOnView(1, isDisplayed(), R.id.toggle))); // check whether slider is displayed recyclerView - .perform(RecyclerViewActions.scrollToPosition(8)) + .perform(scrollToPosition(8)) .check(matches(atPositionOnView(8, isDisplayed(), R.id.seekbar))); // check whether color control button is displayed recyclerView - .perform(RecyclerViewActions.scrollToPosition(9)) + .perform(scrollToPosition(9)) .check(matches(atPositionOnView(9, isDisplayed(), R.id.select_color_button))); // check whether roller shutter button is displayed recyclerView - .perform(RecyclerViewActions.scrollToPosition(10)) + .perform(scrollToPosition(10)) .check(matches(atPositionOnView(10, isDisplayed(), R.id.stop_button))); if (BuildConfig.FLAVOR.equals("full")) { // check whether map view is displayed recyclerView - .perform(RecyclerViewActions.scrollToPosition(13)) + .perform(scrollToPosition(13)) .check(matches(atPositionOnView(13, isDisplayed(), "MapView"))); } } @@ -132,7 +132,8 @@ public class BasicWidgetTest extends TestWithoutIntro { @Override public boolean matchesSafely(final RecyclerView recyclerView) { - RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position); + RecyclerView.ViewHolder viewHolder = + recyclerView.findViewHolderForAdapterPosition(position); View targetView = childCb.findChild(viewHolder.itemView); return itemMatcher.matches(targetView); } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ui/IntroActivityTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ui/IntroActivityTest.java index a197253a3a8870ef7a99fb0fbcacf0cb3d00b6ee..5c8eb5564eb7d4dda9f59252824b9aa32a312638 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ui/IntroActivityTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ui/IntroActivityTest.java @@ -1,14 +1,10 @@ package org.openhab.habdroid.ui; - -import android.support.test.espresso.IdlingRegistry; import android.support.test.espresso.ViewInteraction; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.LargeTest; -import android.view.View; import org.hamcrest.CoreMatchers; -import org.hamcrest.core.IsInstanceOf; import org.junit.Test; import org.junit.runner.RunWith; import org.openhab.habdroid.R; @@ -23,42 +19,35 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withParent; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; + import static org.openhab.habdroid.TestUtils.childAtPosition; @LargeTest @RunWith(AndroidJUnit4.class) public class IntroActivityTest extends TestWithIntro { - @Test public void appShowsIntro() { - ViewInteraction textView = onView( - allOf(withId(R.id.title), withText("Welcome to openHAB"), - childAtPosition( - allOf(withId(R.id.main), - withParent(withId(R.id.view_pager))), - 0), - isDisplayed())); + ViewInteraction textView = onView(allOf( + withId(R.id.title), + withText("Welcome to openHAB"), + childAtPosition(allOf(withId(R.id.main), withParent(withId(R.id.view_pager))), 0), + isDisplayed())); textView.check(matches(withText("Welcome to openHAB"))); - ViewInteraction imageView = onView( - allOf(withId(R.id.image), - childAtPosition( - childAtPosition( - withId(R.id.main), - 1), - 0), - isDisplayed())); + ViewInteraction imageView = onView(allOf( + withId(R.id.image), + childAtPosition(childAtPosition(withId(R.id.main), 1), 0), + isDisplayed())); imageView.check(matches(isDisplayed())); - ViewInteraction textView2 = onView( - allOf(withId(R.id.description), withText("A vendor and technology agnostic open source automation software for your home"), - childAtPosition( - childAtPosition( - withId(R.id.main), - 2), - 0), - isDisplayed())); - textView2.check(matches(withText("A vendor and technology agnostic open source automation software for your home"))); + final String descLabel = + "A vendor and technology agnostic open source automation software for your home"; + ViewInteraction textView2 = onView(allOf( + withId(R.id.description), + withText(descLabel), + childAtPosition(childAtPosition(withId(R.id.main), 2), 0), + isDisplayed())); + textView2.check(matches(withText(descLabel))); ViewInteraction button = onView(allOf(withId(R.id.skip))); button.check(matches(isDisplayed())); @@ -67,15 +56,14 @@ public class IntroActivityTest extends TestWithIntro { imageButton.check(matches(isDisplayed())); // skip intro - ViewInteraction appCompatButton = onView( - allOf(withId(R.id.skip), withText("SKIP"), - childAtPosition( - allOf(withId(R.id.bottomContainer), - childAtPosition( - withId(R.id.bottom), - 1)), - 1), - isDisplayed())); + ViewInteraction appCompatButton = onView(allOf( + withId(R.id.skip), + withText("SKIP"), + childAtPosition(allOf( + withId(R.id.bottomContainer), + childAtPosition(withId(R.id.bottom), 1)), + 1), + isDisplayed())); appCompatButton.perform(click()); appCompatButton.check(doesNotExist()); @@ -87,7 +75,7 @@ public class IntroActivityTest extends TestWithIntro { // Do we see the sitemap? ViewInteraction firstfloor = onView( - CoreMatchers.allOf(withId(R.id.widgetlabel), withText("First Floor"), isDisplayed())); + allOf(withId(R.id.widgetlabel), withText("First Floor"), isDisplayed())); firstfloor.check(matches(withText("First Floor"))); } @@ -96,28 +84,25 @@ public class IntroActivityTest extends TestWithIntro { // click next ViewInteraction appCompatImageButton; for (int i = 0; i < 3; i++) { - appCompatImageButton = onView( - CoreMatchers.allOf(withId(R.id.next), - childAtPosition( - CoreMatchers.allOf(withId(R.id.bottomContainer), - childAtPosition( - withId(R.id.bottom), - 1)), - 3), - isDisplayed())); + appCompatImageButton = onView(allOf( + withId(R.id.next), + childAtPosition(allOf( + withId(R.id.bottomContainer), + childAtPosition(withId(R.id.bottom), 1)), + 3), + isDisplayed())); appCompatImageButton.perform(click()); } // close intro - ViewInteraction appCompatButton = onView( - CoreMatchers.allOf(withId(R.id.done), withText("DONE"), - childAtPosition( - CoreMatchers.allOf(withId(R.id.bottomContainer), - childAtPosition( - withId(R.id.bottom), - 1)), - 4), - isDisplayed())); + ViewInteraction appCompatButton = onView(allOf( + withId(R.id.done), + withText("DONE"), + childAtPosition(allOf( + withId(R.id.bottomContainer), + childAtPosition(withId(R.id.bottom), 1)), + 4), + isDisplayed())); appCompatButton.perform(click()); appCompatButton.check(doesNotExist()); @@ -129,7 +114,7 @@ public class IntroActivityTest extends TestWithIntro { // Do we see the sitemap? ViewInteraction firstfloor = onView( - CoreMatchers.allOf(withId(R.id.widgetlabel), withText("First Floor"), isDisplayed())); + allOf(withId(R.id.widgetlabel), withText("First Floor"), isDisplayed())); firstfloor.check(matches(withText("First Floor"))); } } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ui/NfcTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ui/NfcTest.java index 84cab38b72b5a28b29ed3f4704d29e7cbd1f0f9a..71fca77972afbb26e474881b6fb6c9595ad7602d 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ui/NfcTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ui/NfcTest.java @@ -1,6 +1,7 @@ package org.openhab.habdroid.ui; import android.content.Context; +import android.support.annotation.StringRes; import android.support.test.InstrumentationRegistry; import android.support.test.espresso.ViewInteraction; import android.support.test.espresso.contrib.RecyclerViewActions; @@ -8,7 +9,6 @@ import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.LargeTest; import org.hamcrest.core.IsInstanceOf; -import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.openhab.habdroid.R; @@ -28,7 +28,7 @@ import static org.hamcrest.Matchers.allOf; @RunWith(AndroidJUnit4.class) public class NfcTest extends TestWithoutIntro { @Test - public void nfcTest() throws InterruptedException { + public void nfcTest() { ViewInteraction recyclerView = onView(withId(R.id.recyclerview)); Context context = InstrumentationRegistry.getTargetContext(); @@ -43,21 +43,21 @@ public class NfcTest extends TestWithoutIntro { withText(context.getString(R.string.nfc_dialog_title)))); title.check(matches(withText(context.getString(R.string.nfc_dialog_title)))); - ViewInteraction onButton = onView(withText(context.getString(R.string.nfc_action_on))); - onButton.check(matches(withText(context.getString(R.string.nfc_action_on)))); - - ViewInteraction offButton = onView(withText(context.getString(R.string.nfc_action_off))); - offButton.check(matches(withText(context.getString(R.string.nfc_action_off)))); - - ViewInteraction toggleButton = onView(withText(context.getString(R.string.nfc_action_toggle))); - toggleButton.check(matches(withText(context.getString(R.string.nfc_action_toggle)))); - - ViewInteraction sitemapButton = onView(withText(context.getString(R.string.nfc_action_to_sitemap_page))); - sitemapButton.check(matches(withText(context.getString(R.string.nfc_action_to_sitemap_page)))); + checkViewWithText(context, R.string.nfc_action_off); + checkViewWithText(context, R.string.nfc_action_toggle); + checkViewWithText(context, R.string.nfc_action_to_sitemap_page); + ViewInteraction onButton = checkViewWithText(context, R.string.nfc_action_on); onButton.perform(click()); ViewInteraction imageView = onView(withId(R.id.nfc_watermark)); imageView.check(matches(isDisplayed())); } + + private ViewInteraction checkViewWithText(Context context, @StringRes int stringResId) { + String title = context.getString(stringResId); + ViewInteraction view = onView(withText(title)); + view.check(matches(withText(title))); + return view; + } } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ui/VoiceRecognitionTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ui/VoiceRecognitionTest.java index efa4fe400be6c521069e9f101aeb023e9ac2e378..3e711f1b58beef3b175a5ff34f241aed110ee85d 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ui/VoiceRecognitionTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ui/VoiceRecognitionTest.java @@ -1,5 +1,6 @@ package org.openhab.habdroid.ui; +import android.content.Context; import android.speech.SpeechRecognizer; import android.support.test.InstrumentationRegistry; import android.support.test.espresso.ViewInteraction; @@ -20,21 +21,23 @@ import static org.hamcrest.CoreMatchers.allOf; import static org.junit.Assume.assumeTrue; public class VoiceRecognitionTest extends TestWithoutIntro { - @Rule - public ActivityTestRule<OpenHABMainActivity> mActivityTestRule = new ActivityTestRule<> - (OpenHABMainActivity.class, true, false); + public ActivityTestRule<MainActivity> mActivityTestRule = + new ActivityTestRule<>(MainActivity.class, true, false); @Before public void checkVoiceRecognitionAvailableOnDevice() { + final Context context = InstrumentationRegistry.getTargetContext(); assumeTrue("Voice recognition not available, skipping tests for it.", - SpeechRecognizer.isRecognitionAvailable(InstrumentationRegistry.getTargetContext())); + SpeechRecognizer.isRecognitionAvailable(context)); } @Test - public void checkVoiceAvailbility () { - ViewInteraction voice = onView( - allOf(withId(R.id.mainmenu_voice_recognition), withContentDescription("Voice recognition"), isDisplayed())); + public void checkVoiceAvailbility() { + ViewInteraction voice = onView(allOf( + withId(R.id.mainmenu_voice_recognition), + withContentDescription("Voice recognition"), + isDisplayed())); voice.check(matches(isDisplayed())); } diff --git a/mobile/src/androidTest/java/org/openhab/habdroid/ui/WidgetAdapterTest.java b/mobile/src/androidTest/java/org/openhab/habdroid/ui/WidgetAdapterTest.java index f455ca8a8fc180169403d04636a96f780bed7a33..e68cfa574eea255c88daeb786771528b44cccc26 100644 --- a/mobile/src/androidTest/java/org/openhab/habdroid/ui/WidgetAdapterTest.java +++ b/mobile/src/androidTest/java/org/openhab/habdroid/ui/WidgetAdapterTest.java @@ -5,32 +5,39 @@ import android.support.test.InstrumentationRegistry; import android.support.v7.view.ContextThemeWrapper; import org.junit.Test; +import org.openhab.habdroid.R; +import org.openhab.habdroid.ui.WidgetAdapter.ColorMapper; import static junit.framework.Assert.assertEquals; -import org.openhab.habdroid.R; -import org.openhab.habdroid.ui.OpenHABWidgetAdapter.ColorMapper; - public class WidgetAdapterTest { - private Context context = InstrumentationRegistry.getTargetContext(); + private Context mContext = InstrumentationRegistry.getTargetContext(); @Test public void testColorMappingDarkTheme() { - ColorMapper colorMapper = new ColorMapper(new ContextThemeWrapper(context, R.style.HABDroid_Basic_ui_dark)); - assertEquals("Map #ffffff", Integer.valueOf(0xffffffff), colorMapper.mapColor("#ffffff")); - assertEquals("Must return \"null\" for invalid colors", null, colorMapper.mapColor("#fffzzz")); - assertEquals("Map white => #ffffff in dark themes", Integer.valueOf(0xffffffff), colorMapper.mapColor("white")); - assertEquals("Map red => #ff0000 in dark themes", Integer.valueOf(0xffff0000), colorMapper.mapColor("red")); - assertEquals("Map yellow => #ffff00 in dark themes", Integer.valueOf(0xffffff00), colorMapper.mapColor("yellow")); + final ColorMapper colorMapper = + new ColorMapper(new ContextThemeWrapper(mContext, R.style.HABDroid_Basic_ui_dark)); + testMapping(colorMapper, "Map #ffffff", "#ffffff", 0xffffffff); + testMapping(colorMapper, "Must return \"null\" for invalid colors", "#fffzzz", null); + testMapping(colorMapper, "Map white => #ffffff in dark themes", "white", 0xffffffff); + testMapping(colorMapper, "Map red => #ff0000 in dark themes", "red", 0xffff0000); + testMapping(colorMapper, "Map yellow => #ffff00 in dark themes", "yellow", 0xffffff00); } @Test public void testColorMappingBrightTheme() { - ColorMapper colorMapper = new ColorMapper(new ContextThemeWrapper(context, R.style.HABDroid_Basic_ui)); - assertEquals("Map #ffffff", Integer.valueOf(0xffffffff), colorMapper.mapColor("#ffffff")); - assertEquals("Must return \"null\" for invalid colors", null, colorMapper.mapColor("#fffzzz")); - assertEquals("Map white => #000000 in bright themes", Integer.valueOf(0xff000000), colorMapper.mapColor("white")); - assertEquals("Map red => #ff0000 in bright themes", Integer.valueOf(0xffff0000), colorMapper.mapColor("red")); - assertEquals("Map yellow => #fdd835 in bright themes", Integer.valueOf(0xfffdd835), colorMapper.mapColor("yellow")); + final ColorMapper colorMapper = + new ColorMapper(new ContextThemeWrapper(mContext, R.style.HABDroid_Basic_ui)); + testMapping(colorMapper, "Map #ffffff", "#ffffff", 0xffffffff); + testMapping(colorMapper, "Must return \"null\" for invalid colors", "#fffzzz", null); + testMapping(colorMapper, "Map white => #000000 in bright themes", "white", 0xff000000); + testMapping(colorMapper, "Map red => #ff0000 in bright themes", "red", 0xffff0000); + testMapping(colorMapper, "Map yellow => #fdd835 in bright themes", "yellow", 0xfffdd835); + } + + private static void testMapping(ColorMapper mapper, String message, + String value, Integer expected) { + assertEquals(message, expected != null ? Integer.valueOf(expected) : null, + mapper.mapColor(value)); } } diff --git a/mobile/src/foss/java/org/openhab/habdroid/ui/MapViewHelper.java b/mobile/src/foss/java/org/openhab/habdroid/ui/MapViewHelper.java index ab34233dcc7384f941a319a7586afd73087d320f..3b5db246078293321bccba8149c6802aa737b8ff 100644 --- a/mobile/src/foss/java/org/openhab/habdroid/ui/MapViewHelper.java +++ b/mobile/src/foss/java/org/openhab/habdroid/ui/MapViewHelper.java @@ -6,8 +6,8 @@ import android.view.ViewGroup; import org.openhab.habdroid.core.connection.Connection; public class MapViewHelper { - public static OpenHABWidgetAdapter.ViewHolder createViewHolder(LayoutInflater inflater, - ViewGroup parent, Connection connection, OpenHABWidgetAdapter.ColorMapper colorMapper) { - return new OpenHABWidgetAdapter.GenericViewHolder(inflater, parent, connection, colorMapper); + public static WidgetAdapter.ViewHolder createViewHolder(LayoutInflater inflater, + ViewGroup parent, Connection connection, WidgetAdapter.ColorMapper colorMapper) { + return new WidgetAdapter.GenericViewHolder(inflater, parent, connection, colorMapper); } } diff --git a/mobile/src/full/AndroidManifest.xml b/mobile/src/full/AndroidManifest.xml index bdc4a22077eb92f5916dd2c192e80e67c6255971..ca58433be70ac49c1d4c71e04bbcffc6808f5332 100644 --- a/mobile/src/full/AndroidManifest.xml +++ b/mobile/src/full/AndroidManifest.xml @@ -30,7 +30,7 @@ </service> <service - android:name="org.openhab.habdroid.core.GcmInstanceIDListenerService" + android:name="org.openhab.habdroid.core.GcmInstanceIdListenerService" android:exported="false"> <intent-filter> <action android:name="com.google.android.gms.iid.InstanceID" /> diff --git a/mobile/src/full/java/org/openhab/habdroid/core/CloudMessagingHelper.java b/mobile/src/full/java/org/openhab/habdroid/core/CloudMessagingHelper.java index e6f0f2252ba4b01ec7ff1ea184c23ae803f7d6cd..a8f361df65e572790e348222dfc07350b4be9d05 100644 --- a/mobile/src/full/java/org/openhab/habdroid/core/CloudMessagingHelper.java +++ b/mobile/src/full/java/org/openhab/habdroid/core/CloudMessagingHelper.java @@ -30,7 +30,8 @@ public class CloudMessagingHelper { } public static void onNotificationSelected(Context context, Intent intent) { - int notificationId = intent.getIntExtra(GcmMessageListenerService.EXTRA_NOTIFICATION_ID, -1); + int notificationId = intent.getIntExtra( + GcmMessageListenerService.EXTRA_NOTIFICATION_ID, -1); if (notificationId >= 0) { GcmRegistrationService.scheduleHideNotification(context, notificationId); } diff --git a/mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIDListenerService.java b/mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIdListenerService.java similarity index 89% rename from mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIDListenerService.java rename to mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIdListenerService.java index 4097be0f430616d82d0bcecbd001307379b1dd24..7448ae857374084c08b4e85ba6a02d9446a2edce 100644 --- a/mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIDListenerService.java +++ b/mobile/src/full/java/org/openhab/habdroid/core/GcmInstanceIdListenerService.java @@ -11,7 +11,7 @@ package org.openhab.habdroid.core; import com.google.android.gms.iid.InstanceIDListenerService; -public class GcmInstanceIDListenerService extends InstanceIDListenerService { +public class GcmInstanceIdListenerService extends InstanceIDListenerService { @Override public void onTokenRefresh() { GcmRegistrationService.scheduleRegistration(this); diff --git a/mobile/src/full/java/org/openhab/habdroid/core/GcmMessageListenerService.java b/mobile/src/full/java/org/openhab/habdroid/core/GcmMessageListenerService.java index 5e2f94d0bc4686fc78084cbc66f1a9937c18b921..1db99ff8880691da1f68f9dda7e317634efb86f0 100644 --- a/mobile/src/full/java/org/openhab/habdroid/core/GcmMessageListenerService.java +++ b/mobile/src/full/java/org/openhab/habdroid/core/GcmMessageListenerService.java @@ -32,7 +32,7 @@ import com.google.android.gms.gcm.GcmListenerService; import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; -import org.openhab.habdroid.ui.OpenHABMainActivity; +import org.openhab.habdroid.ui.MainActivity; import org.openhab.habdroid.util.Constants; import org.openhab.habdroid.util.SyncHttpClient; @@ -103,21 +103,23 @@ public class GcmMessageListenerService extends GcmListenerService { } } break; + default: + break; } } private PendingIntent makeNotificationClickIntent(String persistedId, int notificationId) { - Intent contentIntent = new Intent(this, OpenHABMainActivity.class) - .setAction(OpenHABMainActivity.ACTION_NOTIFICATION_SELECTED) + Intent contentIntent = new Intent(this, MainActivity.class) + .setAction(MainActivity.ACTION_NOTIFICATION_SELECTED) .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP) .putExtra(EXTRA_NOTIFICATION_ID, notificationId) - .putExtra(OpenHABMainActivity.EXTRA_PERSISTED_NOTIFICATION_ID, persistedId); + .putExtra(MainActivity.EXTRA_PERSISTED_NOTIFICATION_ID, persistedId); return PendingIntent.getActivity(this, notificationId, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT); } private Notification makeNotification(String msg, String channelId, String icon, - long timestamp, String persistedId, int notificationId) { + long timestamp, String persistedId, int notificationId) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); String toneSetting = prefs.getString(Constants.PREFERENCE_TONE, ""); Bitmap iconBitmap = null; @@ -149,7 +151,8 @@ public class GcmMessageListenerService extends GcmListenerService { .setSound(Uri.parse(toneSetting)) .setContentText(msg) .setContentIntent(contentIntent) - .setDeleteIntent(GcmRegistrationService.createHideNotificationIntent(this, notificationId)) + .setDeleteIntent(GcmRegistrationService.createHideNotificationIntent(this, + notificationId)) .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) .setPublicVersion(publicVersion) .build(); @@ -172,7 +175,8 @@ public class GcmMessageListenerService extends GcmListenerService { .setContentText(text) .setPublicVersion(publicVersion) .setContentIntent(clickIntent) - .setDeleteIntent(GcmRegistrationService.createHideNotificationIntent(this, SUMMARY_NOTIFICATION_ID)) + .setDeleteIntent(GcmRegistrationService.createHideNotificationIntent(this, + SUMMARY_NOTIFICATION_ID)) .build(); } @@ -182,9 +186,11 @@ public class GcmMessageListenerService extends GcmListenerService { String vibration = prefs.getString(Constants.PREFERENCE_NOTIFICATION_VIBRATION, ""); if (getString(R.string.settings_notification_vibration_value_short).equals(vibration)) { vibrationPattern = new long[] {0, 500, 500}; - } else if (getString(R.string.settings_notification_vibration_value_long).equals(vibration)) { + } else if (getString(R.string.settings_notification_vibration_value_long) + .equals(vibration)) { vibrationPattern = new long[] {0, 1000, 1000}; - } else if (getString(R.string.settings_notification_vibration_value_twice).equals(vibration)) { + } else if (getString(R.string.settings_notification_vibration_value_twice) + .equals(vibration)) { vibrationPattern = new long[] {0, 1000, 1000, 1000, 1000}; } else { vibrationPattern = new long[] {0}; @@ -206,9 +212,9 @@ public class GcmMessageListenerService extends GcmListenerService { @TargetApi(23) private int getGcmNotificationCount(StatusBarNotification[] active) { int count = 0; - for (int i = 0; i < active.length; i++) { - String groupKey = active[i].getGroupKey(); - if (active[i].getId() != 0 && groupKey != null && groupKey.endsWith("gcm")) { + for (StatusBarNotification n : active) { + String groupKey = n.getGroupKey(); + if (n.getId() != 0 && groupKey != null && groupKey.endsWith("gcm")) { count++; } } diff --git a/mobile/src/full/java/org/openhab/habdroid/core/GcmRegistrationService.java b/mobile/src/full/java/org/openhab/habdroid/core/GcmRegistrationService.java index 16eaaf201b4a0576ff9902636da55dbb1b4230f7..516d6fcb46b0eb7811dfe6d522878cf748c61e21 100644 --- a/mobile/src/full/java/org/openhab/habdroid/core/GcmRegistrationService.java +++ b/mobile/src/full/java/org/openhab/habdroid/core/GcmRegistrationService.java @@ -38,7 +38,8 @@ public class GcmRegistrationService extends JobIntentService { private static final int JOB_ID = 1000; private static final String ACTION_REGISTER = "org.openhab.habdroid.action.REGISTER_GCM"; - private static final String ACTION_HIDE_NOTIFICATION = "org.openhab.habdroid.action.HIDE_NOTIFICATION"; + private static final String ACTION_HIDE_NOTIFICATION = + "org.openhab.habdroid.action.HIDE_NOTIFICATION"; private static final String EXTRA_NOTIFICATION_ID = "notificationId"; static void scheduleRegistration(Context context) { @@ -87,31 +88,35 @@ public class GcmRegistrationService extends JobIntentService { CloudMessagingHelper.sRegistrationDone = true; break; case ACTION_HIDE_NOTIFICATION: - int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); - if (notificationId >= 0) { + int id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); + if (id >= 0) { try { - sendHideNotificationRequest(notificationId, connection.getMessagingSenderId()); + sendHideNotificationRequest(id, connection.getMessagingSenderId()); } catch (IOException e) { Log.e(TAG, "Failed sending notification hide message", e); } } break; + default: + break; } } private void registerGcm(CloudConnection connection) throws IOException { - InstanceID instanceID = InstanceID.getInstance(this); - String token = instanceID.getToken(connection.getMessagingSenderId(), + InstanceID instanceId = InstanceID.getInstance(this); + String token = instanceId.getToken(connection.getMessagingSenderId(), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); String deviceModel = URLEncoder.encode(Build.MODEL, "UTF-8"); - String deviceId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); + String deviceId = + Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID); String regUrl = String.format(Locale.US, "addAndroidRegistration?deviceId=%s&deviceModel=%s®Id=%s", deviceId, deviceModel, token); Log.d(TAG, "Register device at openHAB-cloud with URL: " + regUrl); - SyncHttpClient.HttpStatusResult result = connection.getSyncHttpClient().get(regUrl).asStatus(); + SyncHttpClient.HttpStatusResult result = + connection.getSyncHttpClient().get(regUrl).asStatus(); if (result.isSuccessful()) { Log.d(TAG, "GCM reg id success"); } else { @@ -120,7 +125,8 @@ public class GcmRegistrationService extends JobIntentService { CloudMessagingHelper.sRegistrationFailureReason = result.error; } - private void sendHideNotificationRequest(int notificationId, String senderId) throws IOException { + private void sendHideNotificationRequest(int notificationId, String senderId) + throws IOException { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); Bundle sendBundle = new Bundle(); sendBundle.putString("type", "hideNotification"); diff --git a/mobile/src/full/java/org/openhab/habdroid/ui/MapViewHelper.java b/mobile/src/full/java/org/openhab/habdroid/ui/MapViewHelper.java index 3aa9d2cb07270de4da926ab2c7bf32d2b8fd0976..33bf0d64fb56e998964a2dccdc5bd700d63b6e4d 100644 --- a/mobile/src/full/java/org/openhab/habdroid/ui/MapViewHelper.java +++ b/mobile/src/full/java/org/openhab/habdroid/ui/MapViewHelper.java @@ -17,30 +17,30 @@ import com.google.android.gms.maps.model.MarkerOptions; import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; -import org.openhab.habdroid.model.OpenHABItem; -import org.openhab.habdroid.model.OpenHABWidget; +import org.openhab.habdroid.model.Item; +import org.openhab.habdroid.model.Widget; import org.openhab.habdroid.util.Util; import java.util.ArrayList; import java.util.Locale; public class MapViewHelper { - public static OpenHABWidgetAdapter.ViewHolder createViewHolder(LayoutInflater inflater, - ViewGroup parent, Connection connection, OpenHABWidgetAdapter.ColorMapper colorMapper) { + public static WidgetAdapter.ViewHolder createViewHolder(LayoutInflater inflater, + ViewGroup parent, Connection connection, WidgetAdapter.ColorMapper colorMapper) { MapsInitializer.initialize(inflater.getContext()); return new GoogleMapsViewHolder(inflater, parent, connection, colorMapper); } - private static class GoogleMapsViewHolder extends OpenHABWidgetAdapter.LabeledItemBaseViewHolder + private static class GoogleMapsViewHolder extends WidgetAdapter.LabeledItemBaseViewHolder implements GoogleMap.OnMarkerDragListener { private final MapView mMapView; private final int mRowHeightPixels; private GoogleMap mMap; - private OpenHABItem mBoundItem; + private Item mBoundItem; private boolean mStarted; public GoogleMapsViewHolder(LayoutInflater inflater, ViewGroup parent, - Connection connection, OpenHABWidgetAdapter.ColorMapper colorMapper) { + Connection connection, WidgetAdapter.ColorMapper colorMapper) { super(inflater, parent, R.layout.openhabwidgetlist_mapitem, connection, colorMapper); mMapView = itemView.findViewById(R.id.mapview); @@ -61,7 +61,7 @@ public class MapViewHelper { } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); ViewGroup.LayoutParams lp = mMapView.getLayoutParams(); @@ -113,7 +113,7 @@ public class MapViewHelper { public void onMarkerDragEnd(Marker marker) { String newState = String.format(Locale.US, "%f,%f", marker.getPosition().latitude, marker.getPosition().longitude); - OpenHABItem item = (OpenHABItem) marker.getTag(); + Item item = (Item) marker.getTag(); Util.sendItemCommand(mConnection.getAsyncHttpClient(), item, newState); } @@ -147,7 +147,7 @@ public class MapViewHelper { boolean canDragMarker = allowDrag && !mBoundItem.readOnly(); if (!mBoundItem.members().isEmpty()) { ArrayList<LatLng> positions = new ArrayList<>(); - for (OpenHABItem item : mBoundItem.members()) { + for (Item item : mBoundItem.members()) { LatLng position = parseLocation(item.state()); if (position != null) { setMarker(map, position, item, item.label(), canDragMarker); @@ -174,7 +174,7 @@ public class MapViewHelper { } } - private static void setMarker(GoogleMap map, LatLng position, OpenHABItem item, + private static void setMarker(GoogleMap map, LatLng position, Item item, CharSequence label, boolean canDrag) { MarkerOptions marker = new MarkerOptions() .draggable(canDrag) diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index bb796743f66bb464fef59b44c37e6f1098822ba3..ae48c86dac85503096d7d36014b960639cb79e3b 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -24,9 +24,9 @@ android:supportsPictureInPicture="false" android:theme="@style/HABDroid.Light" android:supportsRtl="true" - android:name=".core.OpenHABApplication"> + android:name=".core.HabDroidApplication"> <activity - android:name="org.openhab.habdroid.ui.OpenHABPreferencesActivity" + android:name="org.openhab.habdroid.ui.PreferencesActivity" android:label="@string/app_preferences_name"> <intent-filter> <action android:name="android.intent.action.APPLICATION_PREFERENCES" /> @@ -34,13 +34,13 @@ </intent-filter> <meta-data android:name="android.support.PARENT_ACTIVITY" - android:value="org.openhab.habdroid.ui.OpenHABMainActivity" /> + android:value="org.openhab.habdroid.ui.MainActivity" /> </activity> <activity android:name="org.openhab.habdroid.ui.AboutActivity" android:label="@string/about_title"/> <activity - android:name="org.openhab.habdroid.ui.OpenHABMainActivity" + android:name="org.openhab.habdroid.ui.MainActivity" android:label="@string/app_name" android:launchMode="singleTop"> <!-- for Nougat --> @@ -69,7 +69,7 @@ </intent-filter> </activity> <activity - android:name="org.openhab.habdroid.ui.OpenHABWriteTagActivity" + android:name="org.openhab.habdroid.ui.WriteTagActivity" android:label="@string/title_activity_openhabwritetag" /> <activity android:name="org.openhab.habdroid.ui.IntroActivity" android:label="@string/app_intro"/> @@ -77,7 +77,7 @@ android:theme="@style/Theme.AppCompat.Translucent" android:excludeFromRecents="true" /> <service - android:name=".core.OpenHABVoiceService" + android:name=".core.VoiceService" android:exported="false" /> <receiver diff --git a/mobile/src/main/java/de/duenndns/ssl/MemorizingActivity.java b/mobile/src/main/java/de/duenndns/ssl/MemorizingActivity.java index b433e60a5672cbd33e889824719ddc1a2bc5a7d4..7de0d0a6d2a13a62ef5f2583b131d4c763d0e194 100644 --- a/mobile/src/main/java/de/duenndns/ssl/MemorizingActivity.java +++ b/mobile/src/main/java/de/duenndns/ssl/MemorizingActivity.java @@ -53,7 +53,7 @@ public class MemorizingActivity extends Activity @Override public void onCreate(Bundle savedInstanceState) { - mThemedContext = new ContextThemeWrapper(this, Util.getActivityThemeID(this)); + mThemedContext = new ContextThemeWrapper(this, Util.getActivityThemeId(this)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { TypedValue typedValue = new TypedValue(); diff --git a/mobile/src/main/java/de/duenndns/ssl/MemorizingTrustManager.java b/mobile/src/main/java/de/duenndns/ssl/MemorizingTrustManager.java index fc6c7318163f4f1c9f5bd51f901982e644ee0018..388e0a205285d0948440e510d01fafa5bfeb894f 100644 --- a/mobile/src/main/java/de/duenndns/ssl/MemorizingTrustManager.java +++ b/mobile/src/main/java/de/duenndns/ssl/MemorizingTrustManager.java @@ -95,7 +95,7 @@ public class MemorizingTrustManager implements X509TrustManager { Activity foregroundAct; NotificationManager notificationManager; private static int decisionId = 0; - private static SparseArray<MTMDecision> openDecisions = new SparseArray<MTMDecision>(); + private static SparseArray<MTMDecision> openDecisions = new SparseArray<>(); Handler masterHandler; private File keyStoreFile; diff --git a/mobile/src/main/java/org/openhab/habdroid/core/OpenHABApplication.java b/mobile/src/main/java/org/openhab/habdroid/core/HabDroidApplication.java similarity index 86% rename from mobile/src/main/java/org/openhab/habdroid/core/OpenHABApplication.java rename to mobile/src/main/java/org/openhab/habdroid/core/HabDroidApplication.java index d0ad01830b6b7dce319c3587d88bb0e04988882a..784dc0a243db5dfb37b86c847635a6aaaaad89b0 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/OpenHABApplication.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/HabDroidApplication.java @@ -4,7 +4,7 @@ import android.support.multidex.MultiDexApplication; import org.openhab.habdroid.core.connection.ConnectionFactory; -public class OpenHABApplication extends MultiDexApplication { +public class HabDroidApplication extends MultiDexApplication { @Override public void onCreate() { super.onCreate(); diff --git a/mobile/src/main/java/org/openhab/habdroid/core/OpenHABVoiceService.java b/mobile/src/main/java/org/openhab/habdroid/core/VoiceService.java similarity index 94% rename from mobile/src/main/java/org/openhab/habdroid/core/OpenHABVoiceService.java rename to mobile/src/main/java/org/openhab/habdroid/core/VoiceService.java index 2f44f9edc5120abb9010cb7f978f6cb568bf22f2..7f48b82914fc3c86478b74425e36d5616061e3b2 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/OpenHABVoiceService.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/VoiceService.java @@ -19,6 +19,8 @@ import android.support.v4.content.ContextCompat; import android.util.Log; import android.widget.Toast; +import es.dmoral.toasty.Toasty; + import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; @@ -29,17 +31,15 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -import es.dmoral.toasty.Toasty; - /** * This service handles voice commands and sends them to openHAB. */ -public class OpenHABVoiceService extends IntentService { - private static final String TAG = OpenHABVoiceService.class.getSimpleName(); +public class VoiceService extends IntentService { + private static final String TAG = VoiceService.class.getSimpleName(); private Handler mHandler = new Handler(Looper.getMainLooper()); - public OpenHABVoiceService() { - super("OpenHABVoiceService"); + public VoiceService() { + super("VoiceService"); } @Override diff --git a/mobile/src/main/java/org/openhab/habdroid/core/connection/AbstractConnection.java b/mobile/src/main/java/org/openhab/habdroid/core/connection/AbstractConnection.java index 0055cc051877a7fa505a00e0a56903d87488c416..98e1c3414b70e5888e1ecf50cf20e2117c25c043 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/connection/AbstractConnection.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/connection/AbstractConnection.java @@ -1,92 +1,90 @@ package org.openhab.habdroid.core.connection; -import android.content.Context; -import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.util.Log; +import okhttp3.OkHttpClient; + import org.openhab.habdroid.util.AsyncHttpClient; -import org.openhab.habdroid.util.HttpClient; import org.openhab.habdroid.util.SyncHttpClient; import java.net.InetSocketAddress; import java.net.Socket; import java.net.URL; -import okhttp3.OkHttpClient; - public abstract class AbstractConnection implements Connection { private static final String TAG = AbstractConnection.class.getSimpleName(); - private int connectionType; - private String username; - private String password; - private String baseUrl; + private final int mConnectionType; + private final String mUserName; + private final String mPassword; + private final String mBaseUrl; - private final AsyncHttpClient asyncHttpClient; - private final SyncHttpClient syncHttpClient; + private final AsyncHttpClient mAsyncHttpClient; + private final SyncHttpClient mSyncHttpClient; AbstractConnection(OkHttpClient httpClient, int connectionType, String baseUrl, String username, String password) { - this.username = username; - this.password = password; - this.baseUrl = baseUrl; - this.connectionType = connectionType; + mUserName = username; + mPassword = password; + mBaseUrl = baseUrl; + mConnectionType = connectionType; - asyncHttpClient = new AsyncHttpClient(httpClient, baseUrl, username, password); - syncHttpClient = new SyncHttpClient(httpClient, baseUrl, username, password); + mAsyncHttpClient = new AsyncHttpClient(httpClient, baseUrl, username, password); + mSyncHttpClient = new SyncHttpClient(httpClient, baseUrl, username, password); } AbstractConnection(@NonNull AbstractConnection base, int connectionType) { - this.username = base.username; - this.password = base.password; - this.baseUrl = base.baseUrl; - this.connectionType = connectionType; + mUserName = base.mUserName; + mPassword = base.mPassword; + mBaseUrl = base.mBaseUrl; + mConnectionType = connectionType; - asyncHttpClient = base.getAsyncHttpClient(); - syncHttpClient = base.getSyncHttpClient(); + mAsyncHttpClient = base.getAsyncHttpClient(); + mSyncHttpClient = base.getSyncHttpClient(); } private boolean hasUsernameAndPassword() { - return getUsername() != null && !getUsername().isEmpty() && getPassword() != null && - !getPassword().isEmpty(); + return getUsername() != null && !getUsername().isEmpty() + && getPassword() != null && !getPassword().isEmpty(); } @Override public AsyncHttpClient getAsyncHttpClient() { - return asyncHttpClient; + return mAsyncHttpClient; } @Override public SyncHttpClient getSyncHttpClient() { - return syncHttpClient; + return mSyncHttpClient; } @Override public String getUsername() { - return username; + return mUserName; } @Override public String getPassword() { - return password; + return mPassword; } @Override public int getConnectionType() { - return connectionType; + return mConnectionType; } @Override public boolean checkReachabilityInBackground() { - Log.d(TAG, "Checking reachability of " + baseUrl); + Log.d(TAG, "Checking reachability of " + mBaseUrl); try { - URL url = new URL(baseUrl); + URL url = new URL(mBaseUrl); int checkPort = url.getPort(); - if (url.getProtocol().equals("http") && checkPort == -1) + if (url.getProtocol().equals("http") && checkPort == -1) { checkPort = 80; - if (url.getProtocol().equals("https") && checkPort == -1) + } else if (url.getProtocol().equals("https") && checkPort == -1) { checkPort = 443; + } Socket s = new Socket(); s.connect(new InetSocketAddress(url.getHost(), checkPort), 1000); Log.d(TAG, "Socket connected"); @@ -101,10 +99,10 @@ public abstract class AbstractConnection implements Connection { @Override public int hashCode() { int result = 17; - result = 31 * result + connectionType; - result = 31 * result + baseUrl.hashCode(); - result = 31 * result + (username != null ? username.hashCode() : 0); - result = 31 * result + (password != null ? password.hashCode() : 0); + result = 31 * result + mConnectionType; + result = 31 * result + mBaseUrl.hashCode(); + result = 31 * result + (mUserName != null ? mUserName.hashCode() : 0); + result = 31 * result + (mPassword != null ? mPassword.hashCode() : 0); return result; } } diff --git a/mobile/src/main/java/org/openhab/habdroid/core/connection/Connection.java b/mobile/src/main/java/org/openhab/habdroid/core/connection/Connection.java index 8816438343c9e043b6ec549680def21162de7dda..7fbe65562737204372b1b81bc59f981bc7a01c94 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/connection/Connection.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/connection/Connection.java @@ -1,6 +1,5 @@ package org.openhab.habdroid.core.connection; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.openhab.habdroid.util.AsyncHttpClient; @@ -42,6 +41,7 @@ public interface Connection { * @return The username used for this connection. */ @Nullable String getUsername(); + @Nullable String getPassword(); /** diff --git a/mobile/src/main/java/org/openhab/habdroid/core/connection/ConnectionFactory.java b/mobile/src/main/java/org/openhab/habdroid/core/connection/ConnectionFactory.java index 77bdc00e7c4c966acd86522ca2ced5ccd93de986..4cf8288357d40af5619dba44615f73f64573fb2f 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/connection/ConnectionFactory.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/connection/ConnectionFactory.java @@ -19,6 +19,10 @@ import android.support.annotation.VisibleForTesting; import android.support.v4.util.Pair; import android.util.Log; +import de.duenndns.ssl.MemorizingTrustManager; +import okhttp3.OkHttpClient; +import okhttp3.internal.tls.OkHostnameVerifier; + import org.openhab.habdroid.core.CloudMessagingHelper; import org.openhab.habdroid.core.connection.exception.ConnectionException; import org.openhab.habdroid.core.connection.exception.NetworkNotAvailableException; @@ -41,16 +45,13 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509KeyManager; -import de.duenndns.ssl.MemorizingTrustManager; -import okhttp3.OkHttpClient; -import okhttp3.internal.tls.OkHostnameVerifier; - /** * A factory class, which is the main entry point to get a Connection to a specific openHAB * server. Use this factory class whenever you need to obtain a connection to load additional - * data from the openHAB server or another supported source (see the constants in {@link Connection}). + * data from the openHAB server or another supported source + * (see the constants in {@link Connection}). */ -final public class ConnectionFactory extends BroadcastReceiver implements +public final class ConnectionFactory extends BroadcastReceiver implements SharedPreferences.OnSharedPreferenceChangeListener, Handler.Callback { private static final String TAG = ConnectionFactory.class.getSimpleName(); private static final List<Integer> LOCAL_CONNECTION_TYPES = Arrays.asList( @@ -75,9 +76,9 @@ final public class ConnectionFactory extends BroadcastReceiver implements private static final int MSG_AVAILABLE_DONE = 2; private static final int MSG_CLOUD_DONE = 3; - private Context ctx; - private SharedPreferences settings; - private MemorizingTrustManager mTrustManager; + private final Context mContext; + private final SharedPreferences mPrefs; + private final MemorizingTrustManager mTrustManager; private OkHttpClient mHttpClient; private String mLastClientCertAlias; @@ -86,12 +87,12 @@ final public class ConnectionFactory extends BroadcastReceiver implements private CloudConnection mCloudConnection; private Connection mAvailableConnection; private ConnectionException mConnectionFailureReason; - private HashSet<UpdateListener> mListeners = new HashSet<>(); + private final HashSet<UpdateListener> mListeners = new HashSet<>(); private boolean mNeedsUpdate; private boolean mIgnoreNextConnectivityChange; private boolean mAvailableInitialized; private boolean mCloudInitialized; - private Object mInitializationLock = new Object(); + private final Object mInitializationLock = new Object(); private HandlerThread mUpdateThread; @VisibleForTesting @@ -102,22 +103,22 @@ final public class ConnectionFactory extends BroadcastReceiver implements @VisibleForTesting public static ConnectionFactory sInstance; - ConnectionFactory(Context ctx, SharedPreferences settings) { - this.ctx = ctx; - this.settings = settings; - this.settings.registerOnSharedPreferenceChangeListener(this); + ConnectionFactory(Context context, SharedPreferences prefs) { + mContext = context; + mPrefs = prefs; + prefs.registerOnSharedPreferenceChangeListener(this); - mTrustManager = new MemorizingTrustManager(ctx); + mTrustManager = new MemorizingTrustManager(context); mHttpClient = new OkHttpClient.Builder() - .cache(CacheManager.getInstance(ctx).getHttpCache()) + .cache(CacheManager.getInstance(context).getHttpCache()) .hostnameVerifier(mTrustManager.wrapHostnameVerifier(OkHostnameVerifier.INSTANCE)) .build(); updateHttpClientForClientCert(true); IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); // Make sure to ignore the initial sticky broadcast, as we're only interested in changes - mIgnoreNextConnectivityChange = ctx.registerReceiver(null, filter) != null; - ctx.registerReceiver(this, filter); + mIgnoreNextConnectivityChange = context.registerReceiver(null, filter) != null; + context.registerReceiver(this, filter); mUpdateThread = new HandlerThread("ConnectionUpdate"); mUpdateThread.start(); @@ -136,7 +137,7 @@ final public class ConnectionFactory extends BroadcastReceiver implements } public static void shutdown() { - sInstance.ctx.unregisterReceiver(sInstance); + sInstance.mContext.unregisterReceiver(sInstance); sInstance.mUpdateThread.quit(); } @@ -177,7 +178,8 @@ final public class ConnectionFactory extends BroadcastReceiver implements // When coming back from background, re-do connectivity check for // local connections, as the reachability of the local server might have // changed since we went to background - NoUrlInformationException nuie = mConnectionFailureReason instanceof NoUrlInformationException + NoUrlInformationException nuie = + mConnectionFailureReason instanceof NoUrlInformationException ? (NoUrlInformationException) mConnectionFailureReason : null; boolean local = mAvailableConnection == mLocalConnection || (nuie != null && nuie.wouldHaveUsedLocalConnection()); @@ -274,10 +276,11 @@ final public class ConnectionFactory extends BroadcastReceiver implements public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE_AVAILABLE: { // update thread + //noinspection unchecked Pair<Connection, Connection> connections = (Pair<Connection, Connection>) msg.obj; Message result = mMainHandler.obtainMessage(MSG_AVAILABLE_DONE); try { - result.obj = determineAvailableConnection(ctx, + result.obj = determineAvailableConnection(mContext, connections.first, connections.second); } catch (ConnectionException e) { result.obj = e; @@ -304,8 +307,9 @@ final public class ConnectionFactory extends BroadcastReceiver implements handleCloudCheckDone((CloudConnection) msg.obj); return true; } + default: + return false; } - return false; } private boolean updateAvailableConnection(Connection c, ConnectionException failureReason) { @@ -365,14 +369,16 @@ final public class ConnectionFactory extends BroadcastReceiver implements @VisibleForTesting public void updateConnections() { - if (settings.getBoolean(Constants.PREFERENCE_DEMOMODE, false)) { + if (mPrefs.getBoolean(Constants.PREFERENCE_DEMOMODE, false)) { mLocalConnection = mRemoteConnection = new DemoConnection(mHttpClient); handleAvailableCheckDone(mLocalConnection, null); handleCloudCheckDone(null); } else { - mLocalConnection = makeConnection(Connection.TYPE_LOCAL, Constants.PREFERENCE_LOCAL_URL, + mLocalConnection = makeConnection(Connection.TYPE_LOCAL, + Constants.PREFERENCE_LOCAL_URL, Constants.PREFERENCE_LOCAL_USERNAME, Constants.PREFERENCE_LOCAL_PASSWORD); - mRemoteConnection = makeConnection(Connection.TYPE_REMOTE, Constants.PREFERENCE_REMOTE_URL, + mRemoteConnection = makeConnection(Connection.TYPE_REMOTE, + Constants.PREFERENCE_REMOTE_URL, Constants.PREFERENCE_REMOTE_USERNAME, Constants.PREFERENCE_REMOTE_PASSWORD); synchronized (mInitializationLock) { @@ -387,11 +393,11 @@ final public class ConnectionFactory extends BroadcastReceiver implements } private void updateHttpClientForClientCert(boolean forceUpdate) { - String clientCertAlias = settings.getBoolean(Constants.PREFERENCE_DEMOMODE, false) + String clientCertAlias = mPrefs.getBoolean(Constants.PREFERENCE_DEMOMODE, false) ? null // No client cert in demo mode - : settings.getString(Constants.PREFERENCE_SSLCLIENTCERT, null); + : mPrefs.getString(Constants.PREFERENCE_SSLCLIENTCERT, null); KeyManager[] keyManagers = clientCertAlias != null - ? new KeyManager[] { new ClientKeyManager(ctx, clientCertAlias) } + ? new KeyManager[] { new ClientKeyManager(mContext, clientCertAlias) } : null; // Updating the SSL socket factory is an expensive call; @@ -441,7 +447,7 @@ final public class ConnectionFactory extends BroadcastReceiver implements private void handleCloudCheckDone(CloudConnection connection) { if (connection != mCloudConnection) { mCloudConnection = connection; - CloudMessagingHelper.onConnectionUpdated(ctx, connection); + CloudMessagingHelper.onConnectionUpdated(mContext, connection); for (UpdateListener l : mListeners) { l.onCloudConnectionChanged(connection); } @@ -470,17 +476,17 @@ final public class ConnectionFactory extends BroadcastReceiver implements private AbstractConnection makeConnection(int type, String urlKey, String userNameKey, String passwordKey) { - String url = Util.normalizeUrl(settings.getString(urlKey, "")); + String url = Util.normalizeUrl(mPrefs.getString(urlKey, "")); if (url.isEmpty()) { return null; } return new DefaultConnection(mHttpClient, type, url, - settings.getString(userNameKey, null), - settings.getString(passwordKey, null)); + mPrefs.getString(userNameKey, null), + mPrefs.getString(passwordKey, null)); } private static class ClientKeyManager implements X509KeyManager { - private final static String TAG = ClientKeyManager.class.getSimpleName(); + private static final String TAG = ClientKeyManager.class.getSimpleName(); private Context mContext; private String mAlias; diff --git a/mobile/src/main/java/org/openhab/habdroid/core/connection/exception/NetworkNotSupportedException.java b/mobile/src/main/java/org/openhab/habdroid/core/connection/exception/NetworkNotSupportedException.java index cdbee254ad01f46854aa886e36b40ed69a17c56c..32555379e6c47d818112588ce9d3d92664c3e716 100644 --- a/mobile/src/main/java/org/openhab/habdroid/core/connection/exception/NetworkNotSupportedException.java +++ b/mobile/src/main/java/org/openhab/habdroid/core/connection/exception/NetworkNotSupportedException.java @@ -3,14 +3,14 @@ package org.openhab.habdroid.core.connection.exception; import android.net.NetworkInfo; public class NetworkNotSupportedException extends ConnectionException { - private final NetworkInfo networkInfo; + private final NetworkInfo mNetworkInfo; public NetworkNotSupportedException(NetworkInfo info) { super(); - networkInfo = info; + mNetworkInfo = info; } public NetworkInfo getNetworkInfo() { - return networkInfo; + return mNetworkInfo; } } diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABNotification.java b/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.java similarity index 84% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABNotification.java rename to mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.java index 87e96ad9122ae1a411d16f5ec0941b5c6697fe61..c0d0fb94d7b61030ed537acdfb9bedc3260ce8d7 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABNotification.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.java @@ -7,11 +7,6 @@ * http://www.eclipse.org/legal/epl-v10.html */ -/** - * Created by belovictor on 03/04/15. - * This class represents a my.openHAB notification - */ - package org.openhab.habdroid.model; import android.support.annotation.Nullable; @@ -26,7 +21,7 @@ import java.text.SimpleDateFormat; import java.util.TimeZone; @AutoValue -public abstract class OpenHABNotification { +public abstract class CloudNotification { public abstract String id(); public abstract String message(); public abstract long createdTimestamp(); @@ -43,10 +38,10 @@ public abstract class OpenHABNotification { abstract Builder icon(@Nullable String icon); abstract Builder severity(@Nullable String severity); - abstract OpenHABNotification build(); + abstract CloudNotification build(); } - public static OpenHABNotification fromJson(JSONObject jsonObject) throws JSONException { + public static CloudNotification fromJson(JSONObject jsonObject) throws JSONException { long created = 0; if (jsonObject.has("created")) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'"); @@ -58,7 +53,7 @@ public abstract class OpenHABNotification { } } - return new AutoValue_OpenHABNotification.Builder() + return new AutoValue_CloudNotification.Builder() .id(jsonObject.getString("_id")) .icon(jsonObject.optString("icon", null)) .severity(jsonObject.optString("severity", null)) diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABItem.java b/mobile/src/main/java/org/openhab/habdroid/model/Item.java similarity index 85% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABItem.java rename to mobile/src/main/java/org/openhab/habdroid/model/Item.java index aa80d0aa46f7c3280c9b992de1f4be2a1474ff9d..44224c8a2ee57d190df3d7b117397dfe98be9500 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABItem.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/Item.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; */ @AutoValue -public abstract class OpenHABItem implements Parcelable { +public abstract class Item implements Parcelable { public enum Type { None, Color, @@ -55,16 +55,16 @@ public abstract class OpenHABItem implements Parcelable { @Nullable public abstract String link(); public abstract boolean readOnly(); - public abstract List<OpenHABItem> members(); + public abstract List<Item> members(); @Nullable - public abstract List<OpenHABLabeledValue> options(); + public abstract List<LabeledValue> options(); @Nullable public abstract String state(); public abstract boolean stateAsBoolean(); public abstract float stateAsFloat(); @SuppressWarnings("mutable") @Nullable - public abstract float[] stateAsHSV(); + public abstract float[] stateAsHsv(); @Nullable public abstract Integer stateAsBrightness(); @@ -81,14 +81,14 @@ public abstract class OpenHABItem implements Parcelable { public abstract Builder state(@Nullable String state); public abstract Builder link(@Nullable String link); public abstract Builder readOnly(boolean readOnly); - public abstract Builder members(List<OpenHABItem> members); - public abstract Builder options(@Nullable List<OpenHABLabeledValue> options); + public abstract Builder members(List<Item> members); + public abstract Builder options(@Nullable List<LabeledValue> options); - public OpenHABItem build() { + public Item build() { String state = state(); return stateAsBoolean(parseAsBoolean(state)) .stateAsFloat(parseAsFloat(state)) - .stateAsHSV(parseAsHSV(state)) + .stateAsHsv(parseAsHsv(state)) .stateAsBrightness(parseAsBrightness(state)) .autoBuild(); } @@ -96,9 +96,9 @@ public abstract class OpenHABItem implements Parcelable { abstract String state(); abstract Builder stateAsBoolean(boolean state); abstract Builder stateAsFloat(float state); - abstract Builder stateAsHSV(float[] hsv); + abstract Builder stateAsHsv(float[] hsv); abstract Builder stateAsBrightness(@Nullable Integer brightness); - abstract OpenHABItem autoBuild(); + abstract Item autoBuild(); private static boolean parseAsBoolean(String state) { // For uninitialized/null state return false @@ -139,7 +139,7 @@ public abstract class OpenHABItem implements Parcelable { } } - private static float[] parseAsHSV(String state) { + private static float[] parseAsHsv(String state) { if (state != null) { String[] stateSplit = state.split(","); if (stateSplit.length == 3) { // We need exactly 3 numbers to operate this @@ -171,7 +171,8 @@ public abstract class OpenHABItem implements Parcelable { return null; } - private final static Pattern HSB_PATTERN = Pattern.compile("^([0-9]*\\.?[0-9]+),([0-9]*\\.?[0-9]+),([0-9]*\\.?[0-9]+)$"); + private static final Pattern HSB_PATTERN = + Pattern.compile("^([0-9]*\\.?[0-9]+),([0-9]*\\.?[0-9]+),([0-9]*\\.?[0-9]+)$"); } private static Type parseType(String type) { @@ -192,7 +193,7 @@ public abstract class OpenHABItem implements Parcelable { } } - public static OpenHABItem fromXml(Node startNode) { + public static Item fromXml(Node startNode) { String name = null, state = null, link = null; Type type = Type.None, groupType = Type.None; if (startNode.hasChildNodes()) { @@ -205,24 +206,24 @@ public abstract class OpenHABItem implements Parcelable { case "name": name = childNode.getTextContent(); break; case "state": state = childNode.getTextContent(); break; case "link": link = childNode.getTextContent(); break; + default: break; } } } - return new AutoValue_OpenHABItem.Builder() + return new AutoValue_Item.Builder() .type(type) .groupType(groupType) .name(name) .label(name) .state("Unitialized".equals(state) ? null : state) - .members(new ArrayList<OpenHABItem>()) + .members(new ArrayList<>()) .link(link) .readOnly(false) .build(); } - public static OpenHABItem updateFromEvent(OpenHABItem item, JSONObject jsonObject) - throws JSONException { + public static Item updateFromEvent(Item item, JSONObject jsonObject) throws JSONException { if (jsonObject == null) { return item; } @@ -234,14 +235,14 @@ public abstract class OpenHABItem implements Parcelable { return builder.build(); } - public static OpenHABItem fromJson(JSONObject jsonObject) throws JSONException { + public static Item fromJson(JSONObject jsonObject) throws JSONException { if (jsonObject == null) { return null; } return parseFromJson(jsonObject).build(); } - private static OpenHABItem.Builder parseFromJson(JSONObject jsonObject) throws JSONException { + private static Item.Builder parseFromJson(JSONObject jsonObject) throws JSONException { String name = jsonObject.getString("name"); String state = jsonObject.optString("state", ""); if ("NULL".equals(state) || "UNDEF".equals(state) || "undefined".equalsIgnoreCase(state)) { @@ -250,23 +251,22 @@ public abstract class OpenHABItem implements Parcelable { JSONObject stateDescription = jsonObject.optJSONObject("stateDescription"); boolean readOnly = stateDescription != null - ? stateDescription.optBoolean("readOnly", false) - : false; + && stateDescription.optBoolean("readOnly", false); - List<OpenHABLabeledValue> options = null; + List<LabeledValue> options = null; if (stateDescription != null && stateDescription.has("options")) { JSONArray optionsJson = stateDescription.getJSONArray("options"); options = new ArrayList<>(); for (int i = 0; i < optionsJson.length(); i++) { JSONObject optionJson = optionsJson.getJSONObject(i); - options.add(OpenHABLabeledValue.newBuilder() + options.add(LabeledValue.newBuilder() .value(optionJson.getString("value")) .label(optionJson.getString("label")) .build()); } } - List<OpenHABItem> members = new ArrayList<>(); + List<Item> members = new ArrayList<>(); JSONArray membersJson = jsonObject.optJSONArray("members"); if (membersJson != null) { for (int i = 0; i < membersJson.length(); i++) { @@ -274,7 +274,7 @@ public abstract class OpenHABItem implements Parcelable { } } - return new AutoValue_OpenHABItem.Builder() + return new AutoValue_Item.Builder() .type(parseType(jsonObject.getString("type"))) .groupType(parseType(jsonObject.optString("groupType"))) .name(name) diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABLabeledValue.java b/mobile/src/main/java/org/openhab/habdroid/model/LabeledValue.java similarity index 75% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABLabeledValue.java rename to mobile/src/main/java/org/openhab/habdroid/model/LabeledValue.java index 9b608f9d326df774a8ea6a0019c9d640cc5c1123..d8f03eefefa3df656c36d64794dfe51d387e1e63 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABLabeledValue.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/LabeledValue.java @@ -14,19 +14,19 @@ import android.os.Parcelable; import com.google.auto.value.AutoValue; @AutoValue -public abstract class OpenHABLabeledValue implements Parcelable { +public abstract class LabeledValue implements Parcelable { public abstract String value(); public abstract String label(); public static Builder newBuilder() { - return new AutoValue_OpenHABLabeledValue.Builder(); + return new AutoValue_LabeledValue.Builder(); } @AutoValue.Builder - public static abstract class Builder { + public abstract static class Builder { public abstract Builder value(String value); public abstract Builder label(String label); - public abstract OpenHABLabeledValue build(); + public abstract LabeledValue build(); } } diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABLinkedPage.java b/mobile/src/main/java/org/openhab/habdroid/model/LinkedPage.java similarity index 84% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABLinkedPage.java rename to mobile/src/main/java/org/openhab/habdroid/model/LinkedPage.java index 05c7d147ef713700d3bc4d5a6c2c7f7aeb92166f..3743fbe547a5b323ff75ce8e3cf78b8ac03fcb27 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABLinkedPage.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/LinkedPage.java @@ -13,7 +13,6 @@ import android.os.Parcelable; import com.google.auto.value.AutoValue; -import org.json.JSONException; import org.json.JSONObject; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -23,7 +22,7 @@ import org.w3c.dom.NodeList; */ @AutoValue -public abstract class OpenHABLinkedPage implements Parcelable { +public abstract class LinkedPage implements Parcelable { public abstract String id(); public abstract String title(); public abstract String icon(); @@ -36,7 +35,7 @@ public abstract class OpenHABLinkedPage implements Parcelable { public abstract Builder icon(String icon); public abstract Builder link(String link); - public OpenHABLinkedPage build() { + public LinkedPage build() { String title = title(); if (title.indexOf('[') > 0) { title(title.substring(0, title.indexOf('['))); @@ -45,10 +44,10 @@ public abstract class OpenHABLinkedPage implements Parcelable { } abstract String title(); - abstract OpenHABLinkedPage autoBuild(); + abstract LinkedPage autoBuild(); } - public static OpenHABLinkedPage fromXml(Node startNode) { + public static LinkedPage fromXml(Node startNode) { String id = null, title = null, icon = null, link = null; if (startNode.hasChildNodes()) { @@ -60,11 +59,12 @@ public abstract class OpenHABLinkedPage implements Parcelable { case "title": title = childNode.getTextContent(); break; case "icon": icon = childNode.getTextContent(); break; case "link": link = childNode.getTextContent(); break; + default: break; } } } - return new AutoValue_OpenHABLinkedPage.Builder() + return new AutoValue_LinkedPage.Builder() .id(id) .title(title) .icon(icon) @@ -72,11 +72,11 @@ public abstract class OpenHABLinkedPage implements Parcelable { .build(); } - public static OpenHABLinkedPage fromJson(JSONObject jsonObject) throws JSONException { + public static LinkedPage fromJson(JSONObject jsonObject) { if (jsonObject == null) { return null; } - return new AutoValue_OpenHABLinkedPage.Builder() + return new AutoValue_LinkedPage.Builder() .id(jsonObject.optString("id", null)) .title(jsonObject.optString("title", null)) .icon(jsonObject.optString("icon", null)) diff --git a/mobile/src/main/java/org/openhab/habdroid/model/ServerProperties.java b/mobile/src/main/java/org/openhab/habdroid/model/ServerProperties.java index e7bcd878306b8cb7edfe48c9909774f7d0ddaf0e..52cd83164115f1f29474f701d06af18e1b03fb6d 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/ServerProperties.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/ServerProperties.java @@ -5,6 +5,10 @@ import android.util.Log; import com.google.auto.value.AutoValue; +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.Request; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -24,10 +28,6 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.Request; - @AutoValue public abstract class ServerProperties implements Parcelable { private static final String TAG = ServerProperties.class.getSimpleName(); @@ -52,12 +52,13 @@ public abstract class ServerProperties implements Parcelable { public interface UpdateSuccessCallback { void handleServerPropertyUpdate(ServerProperties props); } + public interface UpdateFailureCallback { void handleUpdateFailure(Request request, int statusCode, Throwable error); } public abstract int flags(); - public abstract List<OpenHABSitemap> sitemaps(); + public abstract List<Sitemap> sitemaps(); public boolean hasJsonApi() { return (flags() & SERVER_FLAG_JSON_REST_API) != 0; @@ -70,11 +71,13 @@ public abstract class ServerProperties implements Parcelable { abstract Builder toBuilder(); @AutoValue.Builder - static abstract class Builder { + abstract static class Builder { abstract Builder flags(int flags); - abstract Builder sitemaps(List<OpenHABSitemap> sitemaps); + + abstract Builder sitemaps(List<Sitemap> sitemaps); abstract ServerProperties build(); + abstract int flags(); } @@ -144,7 +147,7 @@ public abstract class ServerProperties implements Parcelable { @Override public void onSuccess(String response, Headers headers) { // OH1 returns XML, later versions return JSON - List<OpenHABSitemap> result = (handle.builder.flags() & SERVER_FLAG_JSON_REST_API) != 0 + List<Sitemap> result = (handle.builder.flags() & SERVER_FLAG_JSON_REST_API) != 0 ? loadSitemapsFromJson(response) : loadSitemapsFromXml(response); Log.d(TAG, "Server returned sitemaps: " + result); @@ -154,7 +157,7 @@ public abstract class ServerProperties implements Parcelable { }); } - private static List<OpenHABSitemap> loadSitemapsFromXml(String response) { + private static List<Sitemap> loadSitemapsFromXml(String response) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = dbf.newDocumentBuilder(); @@ -166,7 +169,7 @@ public abstract class ServerProperties implements Parcelable { } } - private static List<OpenHABSitemap> loadSitemapsFromJson(String response) { + private static List<Sitemap> loadSitemapsFromJson(String response) { try { JSONArray jsonArray = new JSONArray(response); return Util.parseSitemapList(jsonArray); diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABSitemap.java b/mobile/src/main/java/org/openhab/habdroid/model/Sitemap.java similarity index 81% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABSitemap.java rename to mobile/src/main/java/org/openhab/habdroid/model/Sitemap.java index 3a4e992b083fab43224bc7dd25f4a990d0df9ad5..4efe841ef69d114034a27127441d53921a16e6c1 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABSitemap.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/Sitemap.java @@ -14,23 +14,22 @@ import android.support.annotation.Nullable; import com.google.auto.value.AutoValue; -import org.json.JSONException; import org.json.JSONObject; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @AutoValue -public abstract class OpenHABSitemap implements Parcelable { - public abstract String name(); +public abstract class Sitemap implements Parcelable { + public abstract String name(); public abstract String label(); - public abstract String link(); - @Nullable + public abstract String link(); + @Nullable public abstract String icon(); public abstract String iconPath(); - public abstract String homepageLink(); + public abstract String homepageLink(); - @AutoValue.Builder - static abstract class Builder { + @AutoValue.Builder + abstract static class Builder { public abstract Builder name(String name); public abstract Builder label(String label); public abstract Builder link(String link); @@ -38,10 +37,10 @@ public abstract class OpenHABSitemap implements Parcelable { public abstract Builder iconPath(String iconPath); public abstract Builder homepageLink(String homepageLink); - public abstract OpenHABSitemap build(); + public abstract Sitemap build(); } - public static OpenHABSitemap fromXml(Node startNode) { + public static Sitemap fromXml(Node startNode) { String label = null, name = null, icon = null, link = null, homepageLink = null; if (startNode.hasChildNodes()) { @@ -65,11 +64,13 @@ public abstract class OpenHABSitemap implements Parcelable { } } break; + default: + break; } } } - return new AutoValue_OpenHABSitemap.Builder() + return new AutoValue_Sitemap.Builder() .name(name) .label(label != null ? label : name) .link(link) @@ -79,19 +80,21 @@ public abstract class OpenHABSitemap implements Parcelable { .build(); } - public static OpenHABSitemap fromJson(JSONObject jsonObject) throws JSONException { + public static Sitemap fromJson(JSONObject jsonObject) { String name = jsonObject.optString("name", null); String label = jsonObject.optString("label", null); String icon = jsonObject.optString("icon", null); JSONObject homepageObject = jsonObject.optJSONObject("homepage"); + String homepageLink = homepageObject != null + ? homepageObject.optString("link", null) : null; - return new AutoValue_OpenHABSitemap.Builder() + return new AutoValue_Sitemap.Builder() .name(name) .label(label != null ? label : name) .icon(icon) .iconPath(String.format("icon/%s", icon)) .link(jsonObject.optString("link", null)) - .homepageLink(homepageObject != null ? homepageObject.optString("link", null) : null) + .homepageLink(homepageLink) .build(); } } diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidget.java b/mobile/src/main/java/org/openhab/habdroid/model/Widget.java similarity index 83% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidget.java rename to mobile/src/main/java/org/openhab/habdroid/model/Widget.java index 4bc4f3f27c4f05b701fd0851a4021f4e1bd06673..6b8cba8dd45c0af2b0ff8cdb4206f2e6f07bbfb4 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidget.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/Widget.java @@ -12,7 +12,6 @@ package org.openhab.habdroid.model; import android.graphics.Color; import android.os.Parcelable; import android.support.annotation.Nullable; -import android.util.Log; import com.google.auto.value.AutoValue; @@ -31,7 +30,7 @@ import java.util.Locale; */ @AutoValue -public abstract class OpenHABWidget implements Parcelable { +public abstract class Widget implements Parcelable { public enum Type { Chart, Colorpicker, @@ -62,10 +61,10 @@ public abstract class OpenHABWidget implements Parcelable { @Nullable public abstract String url(); @Nullable - public abstract OpenHABItem item(); + public abstract Item item(); @Nullable - public abstract OpenHABLinkedPage linkedPage(); - public abstract List<OpenHABLabeledValue> mappings(); + public abstract LinkedPage linkedPage(); + public abstract List<LabeledValue> mappings(); @Nullable public abstract String encoding(); @Nullable @@ -92,9 +91,9 @@ public abstract class OpenHABWidget implements Parcelable { return !getMappingsOrItemOptions().isEmpty(); } - public List<OpenHABLabeledValue> getMappingsOrItemOptions() { - List<OpenHABLabeledValue> mappings = mappings(); - List<OpenHABLabeledValue> options = item() != null ? item().options() : null; + public List<LabeledValue> getMappingsOrItemOptions() { + List<LabeledValue> mappings = mappings(); + List<LabeledValue> options = item() != null ? item().options() : null; return mappings.isEmpty() && options != null ? options : mappings; } @@ -109,9 +108,9 @@ public abstract class OpenHABWidget implements Parcelable { public abstract Builder iconPath(String iconPath); public abstract Builder type(Type type); public abstract Builder url(@Nullable String url); - public abstract Builder item(@Nullable OpenHABItem item); - public abstract Builder linkedPage(@Nullable OpenHABLinkedPage linkedPage); - public abstract Builder mappings(List<OpenHABLabeledValue> mappings); + public abstract Builder item(@Nullable Item item); + public abstract Builder linkedPage(@Nullable LinkedPage linkedPage); + public abstract Builder mappings(List<LabeledValue> mappings); public abstract Builder encoding(@Nullable String encoding); public abstract Builder iconColor(@Nullable String iconColor); public abstract Builder labelColor(@Nullable String labelColor); @@ -125,7 +124,7 @@ public abstract class OpenHABWidget implements Parcelable { public abstract Builder legend(@Nullable Boolean legend); public abstract Builder height(int height); - public OpenHABWidget build() { + public Widget build() { // A 'none' icon equals no icon at all if ("none".equals(icon())) { icon(null); @@ -151,19 +150,19 @@ public abstract class OpenHABWidget implements Parcelable { abstract float minValue(); abstract float maxValue(); abstract float step(); - abstract OpenHABWidget autoBuild(); + abstract Widget autoBuild(); } - public static void parseXml(List<OpenHABWidget> allWidgets, OpenHABWidget parent, Node startNode) { - OpenHABItem item = null; - OpenHABLinkedPage linkedPage = null; + public static void parseXml(List<Widget> allWidgets, Widget parent, Node startNode) { + Item item = null; + LinkedPage linkedPage = null; String id = null, label = null, icon = null, url = null; String period = "", service = "", encoding = null; String iconColor = null, labelColor = null, valueColor = null; Type type = Type.Unknown; float minValue = 0f, maxValue = 100f, step = 1f; int refresh = 0, height = 0; - List<OpenHABLabeledValue> mappings = new ArrayList<>(); + List<LabeledValue> mappings = new ArrayList<>(); List<Node> childWidgetNodes = new ArrayList<>(); if (startNode.hasChildNodes()) { @@ -171,8 +170,8 @@ public abstract class OpenHABWidget implements Parcelable { for (int i = 0; i < childNodes.getLength(); i++) { Node childNode = childNodes.item(i); switch (childNode.getNodeName()) { - case "item": item = OpenHABItem.fromXml(childNode); break; - case "linkedPage": linkedPage = OpenHABLinkedPage.fromXml(childNode); break; + case "item": item = Item.fromXml(childNode); break; + case "linkedPage": linkedPage = LinkedPage.fromXml(childNode); break; case "widget": childWidgetNodes.add(childNode); break; case "type": type = parseType(childNode.getTextContent()); break; case "widgetId": id = childNode.getTextContent(); break; @@ -197,21 +196,29 @@ public abstract class OpenHABWidget implements Parcelable { for (int k = 0; k < mappingChildNodes.getLength(); k++) { Node mappingNode = mappingChildNodes.item(k); switch (mappingNode.getNodeName()) { - case "command": mappingCommand = mappingNode.getTextContent(); break; - case "label": mappingLabel = mappingNode.getTextContent(); break; + case "command": + mappingCommand = mappingNode.getTextContent(); + break; + case "label": + mappingLabel = mappingNode.getTextContent(); + break; + default: + break; } } - OpenHABLabeledValue mapping = OpenHABLabeledValue.newBuilder() + LabeledValue mapping = LabeledValue.newBuilder() .value(mappingCommand) .label(mappingLabel) .build(); mappings.add(mapping); break; + default: + break; } } } - OpenHABWidget widget = new AutoValue_OpenHABWidget.Builder() + Widget widget = new AutoValue_Widget.Builder() .id(id) .parentId(parent != null ? parent.id() : null) .type(type) @@ -241,14 +248,14 @@ public abstract class OpenHABWidget implements Parcelable { } } - public static void parseJson(List<OpenHABWidget> allWidgets, OpenHABWidget parent, + public static void parseJson(List<Widget> allWidgets, Widget parent, JSONObject widgetJson, String iconFormat) throws JSONException { - List<OpenHABLabeledValue> mappings = new ArrayList<>(); + List<LabeledValue> mappings = new ArrayList<>(); if (widgetJson.has("mappings")) { JSONArray mappingsJsonArray = widgetJson.getJSONArray("mappings"); for (int i = 0; i < mappingsJsonArray.length(); i++) { JSONObject mappingObject = mappingsJsonArray.getJSONObject(i); - OpenHABLabeledValue mapping = OpenHABLabeledValue.newBuilder() + LabeledValue mapping = LabeledValue.newBuilder() .value(mappingObject.getString("command")) .label(mappingObject.getString("label")) .build(); @@ -256,15 +263,15 @@ public abstract class OpenHABWidget implements Parcelable { } } - OpenHABItem item = OpenHABItem.fromJson(widgetJson.optJSONObject("item")); + Item item = Item.fromJson(widgetJson.optJSONObject("item")); Type type = parseType(widgetJson.getString("type")); String icon = widgetJson.optString("icon", null); - OpenHABWidget widget = new AutoValue_OpenHABWidget.Builder() + Widget widget = new AutoValue_Widget.Builder() .id(widgetJson.getString("widgetId")) .parentId(parent != null ? parent.id() : null) .item(item) - .linkedPage(OpenHABLinkedPage.fromJson(widgetJson.optJSONObject("linkedPage"))) + .linkedPage(LinkedPage.fromJson(widgetJson.optJSONObject("linkedPage"))) .mappings(mappings) .type(type) .label(widgetJson.optString("label", null)) @@ -295,9 +302,9 @@ public abstract class OpenHABWidget implements Parcelable { } } - public static OpenHABWidget updateFromEvent(OpenHABWidget source, JSONObject eventPayload, + public static Widget updateFromEvent(Widget source, JSONObject eventPayload, String iconFormat) throws JSONException { - OpenHABItem item = OpenHABItem.updateFromEvent( + Item item = Item.updateFromEvent( source.item(), eventPayload.getJSONObject("item")); String iconPath = determineOH2IconPath(item, source.type(), source.icon(), iconFormat, !source.mappings().isEmpty()); @@ -308,11 +315,11 @@ public abstract class OpenHABWidget implements Parcelable { .build(); } - private static String determineOH2IconPath(OpenHABItem item, Type type, String icon, + private static String determineOH2IconPath(Item item, Type type, String icon, String iconFormat, boolean hasMappings) { String itemState = item != null ? item.state() : null; if (itemState != null) { - if (item.isOfTypeOrGroupType(OpenHABItem.Type.Color)) { + if (item.isOfTypeOrGroupType(Item.Type.Color)) { // For items that control a color item fetch the correct icon if (type == Type.Slider || (type == Type.Switch && !hasMappings)) { try { @@ -323,13 +330,13 @@ public abstract class OpenHABWidget implements Parcelable { } catch (Exception e) { itemState = "OFF"; } - } else if (item.stateAsHSV() != null) { - int color = Color.HSVToColor(item.stateAsHSV()); + } else if (item.stateAsHsv() != null) { + int color = Color.HSVToColor(item.stateAsHsv()); itemState = String.format(Locale.US, "#%02x%02x%02x", Color.red(color), Color.green(color), Color.blue(color)); } } else if (type == Type.Switch && !hasMappings - && !item.isOfTypeOrGroupType(OpenHABItem.Type.Rollershutter)) { + && !item.isOfTypeOrGroupType(Item.Type.Rollershutter)) { // For switch items without mappings (just ON and OFF) that control a dimmer item // and which are not ON or OFF already, set the state to "OFF" instead of 0 // or to "ON" to fetch the correct icon diff --git a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidgetDataSource.java b/mobile/src/main/java/org/openhab/habdroid/model/WidgetDataSource.java similarity index 56% rename from mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidgetDataSource.java rename to mobile/src/main/java/org/openhab/habdroid/model/WidgetDataSource.java index dafcb3f444552fe4947c416474b67a67aa3253cb..50aca0484528148dbcd8209ef4c083fc649b0167 100644 --- a/mobile/src/main/java/org/openhab/habdroid/model/OpenHABWidgetDataSource.java +++ b/mobile/src/main/java/org/openhab/habdroid/model/WidgetDataSource.java @@ -26,33 +26,36 @@ import java.util.List; * It uses a sitemap page XML document to create a list of widgets */ -public class OpenHABWidgetDataSource { - private static final String TAG = OpenHABWidgetDataSource.class.getSimpleName(); - private final String iconFormat; - private List<OpenHABWidget> allWidgets = new ArrayList<>(); - private String title; - private String id; - private String icon; - private String link; +public class WidgetDataSource { + private static final String TAG = WidgetDataSource.class.getSimpleName(); - public OpenHABWidgetDataSource(String iconFormat) { - this.iconFormat = iconFormat; + private final String mIconFormat; + private final List<Widget> mAllWidgets = new ArrayList<>(); + private String mTitle; + private String mId; + private String mIcon; + private String mLink; + + public WidgetDataSource(String iconFormat) { + mIconFormat = iconFormat; } public void setSourceNode(Node rootNode) { Log.i(TAG, "Loading new data"); - if (rootNode == null) + if (rootNode == null) { return; + } if (rootNode.hasChildNodes()) { NodeList childNodes = rootNode.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node childNode = childNodes.item(i); switch (childNode.getNodeName()) { - case "widget": OpenHABWidget.parseXml(allWidgets, null, childNode); break; - case "title": title = childNode.getTextContent(); break; - case "id": id = childNode.getTextContent(); break; - case "icon": icon = childNode.getTextContent(); break; - case "link": link = childNode.getTextContent(); break; + case "widget": Widget.parseXml(mAllWidgets, null, childNode); break; + case "title": mTitle = childNode.getTextContent(); break; + case "id": mId = childNode.getTextContent(); break; + case "icon": mIcon = childNode.getTextContent(); break; + case "link": mLink = childNode.getTextContent(); break; + default: break; } } } @@ -60,32 +63,33 @@ public class OpenHABWidgetDataSource { public void setSourceJson(JSONObject jsonObject) { Log.d(TAG, jsonObject.toString()); - if (!jsonObject.has("widgets")) + if (!jsonObject.has("widgets")) { return; + } try { JSONArray jsonWidgetArray = jsonObject.getJSONArray("widgets"); for (int i = 0; i < jsonWidgetArray.length(); i++) { JSONObject widgetJson = jsonWidgetArray.getJSONObject(i); - OpenHABWidget.parseJson(allWidgets, null, widgetJson, iconFormat); + Widget.parseJson(mAllWidgets, null, widgetJson, mIconFormat); } - title = jsonObject.optString("title", null); - id = jsonObject.optString("id", null); - icon = jsonObject.optString("icon", null); - link = jsonObject.optString("link", null); + mTitle = jsonObject.optString("title", null); + mId = jsonObject.optString("id", null); + mIcon = jsonObject.optString("icon", null); + mLink = jsonObject.optString("link", null); } catch (JSONException e) { Log.d(TAG, e.getMessage(), e); } } - public ArrayList<OpenHABWidget> getWidgets() { - ArrayList<OpenHABWidget> result = new ArrayList<OpenHABWidget>(); + public ArrayList<Widget> getWidgets() { + ArrayList<Widget> result = new ArrayList<>(); HashSet<String> firstLevelWidgetIds = new HashSet<>(); - for (OpenHABWidget widget : allWidgets) { + for (Widget widget : mAllWidgets) { if (widget.parentId() == null) { firstLevelWidgetIds.add(widget.id()); } } - for (OpenHABWidget widget : allWidgets) { + for (Widget widget : mAllWidgets) { String parentId = widget.parentId(); if (parentId == null || firstLevelWidgetIds.contains(parentId)) { result.add(widget); @@ -95,27 +99,22 @@ public class OpenHABWidgetDataSource { } public String getTitle() { - String[] splitString; - if (title != null) { - splitString = title.split("\\[|\\]"); - if (splitString.length > 0) { - return splitString[0]; - } else { - return title; - } + if (mTitle != null) { + String[] splitString = mTitle.split("\\[|\\]"); + return splitString.length > 0 ? splitString[0] : mTitle; } return ""; } public String getId() { - return id; + return mId; } public String getIcon() { - return icon; + return mIcon; } public String getLink() { - return link; + return mLink; } } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/AboutActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/AboutActivity.java index 8f4df6c2fb71c30e13dc0cd5aaa73c3511bdfe97..522fe50f9f9cec50fd64fe7a585d412253e381b7 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/AboutActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/AboutActivity.java @@ -45,9 +45,7 @@ import java.util.Locale; import static org.openhab.habdroid.util.Util.obfuscateString; public class AboutActivity extends AppCompatActivity implements - FragmentManager.OnBackStackChangedListener{ - private final static String TAG = AboutActivity.class.getSimpleName(); - + FragmentManager.OnBackStackChangedListener { @Override public void onCreate(Bundle savedInstanceState) { Util.setActivityTheme(this); @@ -103,8 +101,8 @@ public class AboutActivity extends AppCompatActivity implements } public static class AboutMainFragment extends MaterialAboutFragment { - private final static String TAG = AboutMainFragment.class.getSimpleName(); - private final static String URL_TO_GITHUB = "https://github.com/openhab/openhab-android"; + private static final String TAG = AboutMainFragment.class.getSimpleName(); + private static final String URL_TO_GITHUB = "https://github.com/openhab/openhab-android"; private ServerProperties mServerProperties; private Connection mConnection; @@ -115,7 +113,9 @@ public class AboutActivity extends AppCompatActivity implements mServerProperties = getArguments().getParcelable("serverProperties"); try { mConnection = ConnectionFactory.getUsableConnection(); - } catch (ConnectionException ignored) {} + } catch (ConnectionException ignored) { + // ignored + } return super.onCreateView(inflater, container, savedInstanceState); } @@ -140,50 +140,48 @@ public class AboutActivity extends AppCompatActivity implements appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_changelog) .icon(R.drawable.ic_track_changes_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect(URL_TO_GITHUB + "/releases")) + .setOnClickAction(clickRedirect(URL_TO_GITHUB + "/releases")) .build()); appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_source_code) .icon(R.drawable.ic_github_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect(URL_TO_GITHUB)) + .setOnClickAction(clickRedirect(URL_TO_GITHUB)) .build()); appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_issues) .icon(R.drawable.ic_bug_report_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect(URL_TO_GITHUB + "/issues")) + .setOnClickAction(clickRedirect(URL_TO_GITHUB + "/issues")) .build()); appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_license_title) .subText(R.string.about_license) .icon(R.drawable.ic_account_balance_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect(URL_TO_GITHUB + "/blob/master/LICENSE")) + .setOnClickAction(clickRedirect(URL_TO_GITHUB + "/blob/master/LICENSE")) .build()); appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.title_activity_libraries) .icon(R.drawable.ic_developer_mode_grey_24dp) - .setOnClickAction(new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - Fragment f = new LibsBuilder() - .withFields(R.string.class.getFields()) - .withLicenseShown(true) - .withAutoDetect(true) - .supportFragment(); - getFragmentManager() - .beginTransaction() - .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, - R.anim.slide_in_left, R.anim.slide_out_right) - .replace(R.id.about_container, f) - .setBreadCrumbTitle(R.string.title_activity_libraries) - .addToBackStack(null) - .commit(); - } + .setOnClickAction(() -> { + Fragment f = new LibsBuilder() + .withFields(R.string.class.getFields()) + .withLicenseShown(true) + .withAutoDetect(true) + .supportFragment(); + getFragmentManager() + .beginTransaction() + .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, + R.anim.slide_in_left, R.anim.slide_out_right) + .replace(R.id.about_container, f) + .setBreadCrumbTitle(R.string.title_activity_libraries) + .addToBackStack(null) + .commit(); }) .build()); appCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_privacy_policy) .icon(R.drawable.ic_security_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect("https://www.openhabfoundation.org/privacy.html")) + .setOnClickAction( + clickRedirect("https://www.openhabfoundation.org/privacy.html")) .build()); MaterialAboutCard.Builder ohServerCard = new MaterialAboutCard.Builder(); @@ -237,22 +235,22 @@ public class AboutActivity extends AppCompatActivity implements ohCommunityCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_docs) .icon(R.drawable.ic_collections_bookmark_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect("https://www.openhab.org/docs/")) + .setOnClickAction(clickRedirect("https://www.openhab.org/docs/")) .build()); ohCommunityCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_community_forum) .icon(R.drawable.ic_forum_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect("https://community.openhab.org/")) + .setOnClickAction(clickRedirect("https://community.openhab.org/")) .build()); ohCommunityCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_translation) .icon(R.drawable.ic_language_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect("https://crowdin.com/profile/openhab-bot")) + .setOnClickAction(clickRedirect("https://crowdin.com/profile/openhab-bot")) .build()); ohCommunityCard.addItem(new MaterialAboutActionItem.Builder() .text(R.string.about_foundation) .icon(R.drawable.ic_people_grey_24dp) - .setOnClickAction(MaterialAboutItemOnClickRedirect("https://www.openhabfoundation.org/")) + .setOnClickAction(clickRedirect("https://www.openhabfoundation.org/")) .build()); return new MaterialAboutList.Builder() @@ -264,17 +262,14 @@ public class AboutActivity extends AppCompatActivity implements @Override protected int getTheme() { - return Util.getActivityThemeID(getActivity()); + return Util.getActivityThemeId(getActivity()); } - private MaterialAboutItemOnClickAction MaterialAboutItemOnClickRedirect(final String url) { - return new MaterialAboutItemOnClickAction() { - @Override - public void onClick() { - Uri uri = Uri.parse(url); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } + private MaterialAboutItemOnClickAction clickRedirect(final String url) { + return () -> { + Uri uri = Uri.parse(url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivity(intent); }; } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/AnchorWebViewClient.java b/mobile/src/main/java/org/openhab/habdroid/ui/AnchorWebViewClient.java index 3cdd3387f0b9ea19ce7fa917e795b2869aa3bdfa..b9c6d14cc6ffaabc7ed72f6eb4f17f31fb243f50 100755 --- a/mobile/src/main/java/org/openhab/habdroid/ui/AnchorWebViewClient.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/AnchorWebViewClient.java @@ -11,38 +11,40 @@ package org.openhab.habdroid.ui; import android.util.Log; +import android.webkit.HttpAuthHandler; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.webkit.HttpAuthHandler; class AnchorWebViewClient extends WebViewClient { private static final String TAG = AnchorWebViewClient.class.getSimpleName(); - private String anchor = null; - private String username; - private String password; + + private String mAnchor; + private String mUserName; + private String mPassword; public AnchorWebViewClient(String url, String username, String password) { - this.username = username; - this.password = password; + mUserName = username; + mPassword = password; int pos = url.lastIndexOf("#") + 1; - if(pos != 0 && pos<url.length()) { - this.anchor = url.substring(pos); - Log.d(TAG, "Found anchor " + anchor + " from url "+ url); + if (pos != 0 && pos < url.length()) { + mAnchor = url.substring(pos); + Log.d(TAG, "Found anchor " + mAnchor + " from url " + url); } else { - Log.d(TAG, "Did not find anchor from url "+ url); + Log.d(TAG, "Did not find anchor from url " + url); } } @Override - public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { - handler.proceed(this.username, this.password); + public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, + String host, String realm) { + handler.proceed(mUserName, mPassword); } @Override public void onPageFinished(WebView view, String url) { - if (anchor != null && !anchor.isEmpty()) { - Log.d(TAG, "Now jumping to anchor " + anchor); - view.loadUrl("javascript:location.hash = '#" + anchor + "';"); + if (mAnchor != null && !mAnchor.isEmpty()) { + Log.d(TAG, "Now jumping to anchor " + mAnchor); + view.loadUrl("javascript:location.hash = '#" + mAnchor + "';"); } } } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationAdapter.java b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationAdapter.java similarity index 91% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationAdapter.java rename to mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationAdapter.java index 082b04e94196992ea10ee45235c946d31000d9ce..02321cd7fa38f966bb426f211c9aefb22ef887d4 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationAdapter.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationAdapter.java @@ -11,6 +11,7 @@ package org.openhab.habdroid.ui; import android.content.Context; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; @@ -23,14 +24,14 @@ import android.widget.TextView; import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; -import org.openhab.habdroid.model.OpenHABNotification; +import org.openhab.habdroid.model.CloudNotification; import org.openhab.habdroid.ui.widget.WidgetImageView; import java.util.ArrayList; import java.util.List; import java.util.Locale; -public class OpenHABNotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { +public class CloudNotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public interface LoadMoreListener { void loadMoreItems(); } @@ -38,23 +39,21 @@ public class OpenHABNotificationAdapter extends RecyclerView.Adapter<RecyclerVie private static final int VIEW_TYPE_NOTIFICATION = 0; private static final int VIEW_TYPE_LOADING = 1; - private final ArrayList<OpenHABNotification> mItems = new ArrayList<>(); + private final ArrayList<CloudNotification> mItems = new ArrayList<>(); private final LayoutInflater mInflater; - private final Context mContext; private final LoadMoreListener mLoadMoreListener; private boolean mHasMoreItems; private boolean mWaitingForMoreData; private int mHighlightedPosition = -1; - public OpenHABNotificationAdapter(Context context, LoadMoreListener loadMoreListener) { + public CloudNotificationAdapter(Context context, LoadMoreListener loadMoreListener) { super(); - mContext = context; mInflater = LayoutInflater.from(context); mLoadMoreListener = loadMoreListener; mHasMoreItems = false; } - public void addLoadedItems(List<OpenHABNotification> items, boolean hasMoreItems) { + public void addLoadedItems(List<CloudNotification> items, boolean hasMoreItems) { mItems.addAll(items); mHasMoreItems = hasMoreItems; mWaitingForMoreData = false; @@ -92,6 +91,7 @@ public class OpenHABNotificationAdapter extends RecyclerView.Adapter<RecyclerVie return position == mItems.size() ? VIEW_TYPE_LOADING : VIEW_TYPE_NOTIFICATION; } + @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_LOADING) { @@ -144,7 +144,7 @@ public class OpenHABNotificationAdapter extends RecyclerView.Adapter<RecyclerVie mIconView = itemView.findViewById(R.id.notificationImage); } - public void bind(OpenHABNotification notification) { + public void bind(CloudNotification notification) { mCreatedView.setText(DateUtils.getRelativeDateTimeString(mCreatedView.getContext(), notification.createdTimestamp(), DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0)); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationFragment.java b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.java similarity index 87% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationFragment.java rename to mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.java index d9c3d6c48ec048c2087f31c82a628df623854c97..f0b12ef61f59e99d585c9f7c10685484350ec2bc 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABNotificationFragment.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.java @@ -10,6 +10,7 @@ package org.openhab.habdroid.ui; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; @@ -23,13 +24,17 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.Request; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; -import org.openhab.habdroid.model.OpenHABNotification; +import org.openhab.habdroid.model.CloudNotification; import org.openhab.habdroid.ui.widget.DividerItemDecoration; import org.openhab.habdroid.util.AsyncHttpClient; import org.openhab.habdroid.util.Util; @@ -37,22 +42,18 @@ import org.openhab.habdroid.util.Util; import java.util.ArrayList; import java.util.Locale; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.Request; - -public class OpenHABNotificationFragment extends Fragment implements +public class CloudNotificationListFragment extends Fragment implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { - private static final String TAG = OpenHABNotificationFragment.class.getSimpleName(); + private static final String TAG = CloudNotificationListFragment.class.getSimpleName(); private static final int PAGE_SIZE = 20; - private OpenHABMainActivity mActivity; + private MainActivity mActivity; // keeps track of current request to cancel it in onPause private Call mRequestHandle; - private OpenHABNotificationAdapter mNotificationAdapter; + private CloudNotificationAdapter mNotificationAdapter; private String mInitiallyHighlightedId; private RecyclerView mRecyclerView; @@ -64,8 +65,8 @@ public class OpenHABNotificationFragment extends Fragment implements private View mRetryButton; private int mLoadOffset; - public static OpenHABNotificationFragment newInstance(@Nullable String highlightedId) { - OpenHABNotificationFragment f = new OpenHABNotificationFragment(); + public static CloudNotificationListFragment newInstance(@Nullable String highlightedId) { + CloudNotificationListFragment f = new CloudNotificationListFragment(); Bundle args = new Bundle(); args.putString("highlightedId", highlightedId); f.setArguments(args); @@ -76,12 +77,12 @@ public class OpenHABNotificationFragment extends Fragment implements * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). */ - public OpenHABNotificationFragment() { + public CloudNotificationListFragment() { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { // Inflate the layout for this fragment Log.i(TAG, "onCreateView"); View view = inflater.inflate(R.layout.openhabnotificationlist_fragment, container, false); @@ -101,8 +102,8 @@ public class OpenHABNotificationFragment extends Fragment implements @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mActivity = (OpenHABMainActivity) getActivity(); - mNotificationAdapter = new OpenHABNotificationAdapter(mActivity, + mActivity = (MainActivity) getActivity(); + mNotificationAdapter = new CloudNotificationAdapter(mActivity, () -> loadNotifications(false)); mLayoutManager = new LinearLayoutManager(mActivity); @@ -167,15 +168,16 @@ public class OpenHABNotificationFragment extends Fragment implements // we skip that additional effort. final String url = String.format(Locale.US, "api/v1/notifications?limit=%d&skip=%d", PAGE_SIZE, mLoadOffset); - mRequestHandle = conn.getAsyncHttpClient().get(url, new AsyncHttpClient.StringResponseHandler() { + final AsyncHttpClient client = conn.getAsyncHttpClient(); + mRequestHandle = client.get(url, new AsyncHttpClient.StringResponseHandler() { @Override public void onSuccess(String responseBody, Headers headers) { try { - ArrayList<OpenHABNotification> items = new ArrayList<>(); + ArrayList<CloudNotification> items = new ArrayList<>(); JSONArray jsonArray = new JSONArray(responseBody); for (int i = 0; i < jsonArray.length(); i++) { JSONObject sitemapJson = jsonArray.getJSONObject(i); - items.add(OpenHABNotification.fromJson(sitemapJson)); + items.add(CloudNotification.fromJson(sitemapJson)); } Log.d(TAG, "Notifications request success, got " + items.size() + " items"); mLoadOffset += items.size(); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/IntroActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/IntroActivity.java index e4732963faa486257a069ebbfe27e5324515fd23..eff2a7216fa40cb69fedcbce6794b77e0ff5a0b7 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/IntroActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/IntroActivity.java @@ -1,6 +1,7 @@ package org.openhab.habdroid.ui; import android.os.Bundle; +import android.support.annotation.ColorInt; import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; import android.support.annotation.StringRes; @@ -13,33 +14,27 @@ import com.github.paolorotolo.appintro.AppIntroFragment; import org.openhab.habdroid.R; public class IntroActivity extends AppIntro { - int colorOpenHABOrange; - int colorOpenHABOrangeDark; - int colorGrey; - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - colorOpenHABOrange = ContextCompat.getColor(this, R.color.openhab_orange); - colorOpenHABOrangeDark = ContextCompat.getColor(this, R.color.openhab_orange_dark); - colorGrey = ContextCompat.getColor(this, R.color.grey_300); // Add slides - addOHSlide(R.string.intro_welcome, + addSlide(R.string.intro_welcome, R.string.intro_whatis, R.drawable.ic_openhab_appicon_340dp); - addOHSlide(R.string.intro_themes, + addSlide(R.string.intro_themes, R.string.intro_themes_description, R.drawable.ic_color_lens_orange_340dp); - addOHSlide(R.string.mainmenu_openhab_voice_recognition, + addSlide(R.string.mainmenu_openhab_voice_recognition, R.string.intro_voice_description, R.drawable.ic_mic_orange_340dp); - addOHSlide(R.string.intro_nfc, + addSlide(R.string.intro_nfc, R.string.intro_nfc_description, R.drawable.ic_nfc_orange_340dp); + // Change bar color - setBarColor(colorOpenHABOrange); - setSeparatorColor(colorOpenHABOrangeDark); + setBarColor(ContextCompat.getColor(this, R.color.openhab_orange)); + setSeparatorColor(ContextCompat.getColor(this, R.color.openhab_orange_dark)); } /** @@ -68,21 +63,19 @@ public class IntroActivity extends AppIntro { * @param description * @param imageDrawable */ - private void addOHSlide(@StringRes int title, @StringRes int description, - @DrawableRes int imageDrawable) { - addSlide(AppIntroFragment.newInstance(getString(title), - // Title font: null => default - null, - getString(description), - // Description font: null => default - null, - imageDrawable, - // Background color - colorGrey, - // Title color - ContextCompat.getColor(getApplicationContext(), R.color.black), - // Description color - ContextCompat.getColor(getApplicationContext(), R.color.black))); + private void addSlide(@StringRes int title, @StringRes int description, + @DrawableRes int imageDrawable) { + @ColorInt int greyColor = ContextCompat.getColor(this, R.color.grey_300); + @ColorInt int blackColor = ContextCompat.getColor(this, R.color.black); + addSlide(AppIntroFragment.newInstance(getString(title), + null, // Title font: null => default + getString(description), + null, // Description font: null => default + imageDrawable, + greyColor, // Background color + blackColor, // Title color + // Description color + ContextCompat.getColor(this, R.color.black))); // Description color } } \ No newline at end of file diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABMainActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.java similarity index 81% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABMainActivity.java rename to mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.java index 2c2cd20c13e1b7bf15187681a72401cf7ea725de..2f9ae6d82a49e867165b2294cf603d7dfc5ddbd2 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABMainActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.java @@ -15,12 +15,12 @@ import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; @@ -33,7 +33,7 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; -import android.support.annotation.NonNull; +import android.support.annotation.ColorInt; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.design.widget.NavigationView; @@ -62,10 +62,14 @@ import android.view.WindowManager; import android.widget.ProgressBar; import android.widget.Toast; +import es.dmoral.toasty.Toasty; +import okhttp3.Headers; +import okhttp3.Request; + import org.openhab.habdroid.R; import org.openhab.habdroid.core.CloudMessagingHelper; import org.openhab.habdroid.core.OnUpdateBroadcastReceiver; -import org.openhab.habdroid.core.OpenHABVoiceService; +import org.openhab.habdroid.core.VoiceService; import org.openhab.habdroid.core.connection.CloudConnection; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; @@ -73,16 +77,15 @@ import org.openhab.habdroid.core.connection.DemoConnection; import org.openhab.habdroid.core.connection.exception.ConnectionException; import org.openhab.habdroid.core.connection.exception.NetworkNotSupportedException; import org.openhab.habdroid.core.connection.exception.NoUrlInformationException; -import org.openhab.habdroid.model.OpenHABLinkedPage; -import org.openhab.habdroid.model.OpenHABSitemap; +import org.openhab.habdroid.model.LinkedPage; import org.openhab.habdroid.model.ServerProperties; +import org.openhab.habdroid.model.Sitemap; import org.openhab.habdroid.ui.activity.ContentController; +import org.openhab.habdroid.util.AsyncHttpClient; import org.openhab.habdroid.util.AsyncServiceResolver; import org.openhab.habdroid.util.Constants; -import org.openhab.habdroid.util.AsyncHttpClient; import org.openhab.habdroid.util.Util; -import java.io.IOException; import java.lang.reflect.Constructor; import java.net.ConnectException; import java.net.SocketTimeoutException; @@ -99,22 +102,17 @@ import javax.jmdns.ServiceInfo; import javax.net.ssl.SSLException; import javax.net.ssl.SSLPeerUnverifiedException; -import es.dmoral.toasty.Toasty; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.Request; - import static org.openhab.habdroid.util.Util.exceptionHasCause; import static org.openhab.habdroid.util.Util.getHostFromUrl; -public class OpenHABMainActivity extends AppCompatActivity implements +public class MainActivity extends AppCompatActivity implements AsyncServiceResolver.Listener, ConnectionFactory.UpdateListener { public static final String ACTION_NOTIFICATION_SELECTED = "org.openhab.habdroid.action.NOTIFICATION_SELECTED"; public static final String EXTRA_PERSISTED_NOTIFICATION_ID = "persistedNotificationId"; - // Logging TAG - private static final String TAG = OpenHABMainActivity.class.getSimpleName(); + private static final String TAG = MainActivity.class.getSimpleName(); + // Activities request codes private static final int INTRO_REQUEST_CODE = 1001; private static final int SETTINGS_REQUEST_CODE = 1002; @@ -123,27 +121,21 @@ public class OpenHABMainActivity extends AppCompatActivity implements // Drawer item codes private static final int GROUP_ID_SITEMAPS = 1; - // preferences - private SharedPreferences mSettings; + private SharedPreferences mPrefs; private AsyncServiceResolver mServiceResolver; - // Toolbar / Actionbar - private Toolbar mToolbar; - // Drawer Layout private DrawerLayout mDrawerLayout; - // Drawer Toggler private ActionBarDrawerToggle mDrawerToggle; private Menu mDrawerMenu; private ColorStateList mDrawerIconTintList; private RecyclerView.RecycledViewPool mViewPool; private ProgressBar mProgressBar; - // select sitemap dialog - private Dialog mSelectSitemapDialog; + private Dialog mSitemapSelectionDialog; private Snackbar mLastSnackbar; private Connection mConnection; private Uri mPendingNfcData; private String mPendingOpenedNotificationId; - private OpenHABSitemap mSelectedSitemap; + private Sitemap mSelectedSitemap; private ContentController mController; private ServerProperties mServerProperties; private ServerProperties.UpdateHandle mPropsUpdateHandle; @@ -154,7 +146,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements * reset ourselves to fullscreen. * @author Dan Cunningham */ - private BroadcastReceiver dreamReceiver = new BroadcastReceiver() { + private BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i("INTENTFILTER", "Recieved intent: " + intent.toString()); @@ -178,10 +170,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements // Set default values, false means do it one time during the very first launch PreferenceManager.setDefaultValues(this, R.xml.preferences, false); - mSettings = PreferenceManager.getDefaultSharedPreferences(this); + mPrefs = PreferenceManager.getDefaultSharedPreferences(this); // Disable screen timeout if set in preferences - if (mSettings.getBoolean(Constants.PREFERENCE_SCREENTIMEROFF, false)) { + if (mPrefs.getBoolean(Constants.PREFERENCE_SCREENTIMEROFF, false)) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @@ -192,7 +184,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements String controllerClassName = getResources().getString(R.string.controller_class); try { Class<?> controllerClass = Class.forName(controllerClassName); - Constructor<?> constructor = controllerClass.getConstructor(OpenHABMainActivity.class); + Constructor<?> constructor = controllerClass.getConstructor(MainActivity.class); mController = (ContentController) constructor.newInstance(this); } catch (Exception e) { Log.wtf(TAG, "Could not instantiate activity controller class '" @@ -237,32 +229,31 @@ public class OpenHABMainActivity extends AppCompatActivity implements if (savedInstanceState.getBoolean("isSitemapSelectionDialogShown")) { showSitemapSelectionDialog(); } - } else { } processIntent(getIntent()); if (isFullscreenEnabled()) { - registerReceiver(dreamReceiver, new IntentFilter("android.intent.action.DREAMING_STARTED")); - registerReceiver(dreamReceiver, new IntentFilter("android.intent.action.DREAMING_STOPPED")); + IntentFilter filter = new IntentFilter(Intent.ACTION_DREAMING_STARTED); + filter.addAction(Intent.ACTION_DREAMING_STOPPED); + registerReceiver(mDreamReceiver, filter); checkFullscreen(); } // Create a new boolean and preference and set it to true - boolean isFirstStart = mSettings.getBoolean("firstStart", true); + boolean isFirstStart = mPrefs.getBoolean("firstStart", true); - SharedPreferences.Editor prefsEdit = mSettings.edit(); + SharedPreferences.Editor prefsEditor = mPrefs.edit(); // If the activity has never started before... if (isFirstStart) { - // Launch app intro - final Intent i = new Intent(OpenHABMainActivity.this, IntroActivity.class); + final Intent i = new Intent(MainActivity.this, IntroActivity.class); startActivityForResult(i, INTRO_REQUEST_CODE); - prefsEdit.putBoolean("firstStart", false).apply(); + prefsEditor.putBoolean("firstStart", false); } - OnUpdateBroadcastReceiver.updateComparableVersion(prefsEdit); - prefsEdit.apply(); + OnUpdateBroadcastReceiver.updateComparableVersion(prefsEditor); + prefsEditor.apply(); } private void handleConnectionChange() { @@ -270,8 +261,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements showSnackbar(R.string.info_demo_mode_short); } else { boolean hasLocalAndRemote = - ConnectionFactory.getConnection(Connection.TYPE_LOCAL) != null && - ConnectionFactory.getConnection(Connection.TYPE_REMOTE) != null; + ConnectionFactory.getConnection(Connection.TYPE_LOCAL) != null + && ConnectionFactory.getConnection(Connection.TYPE_REMOTE) != null; int type = mConnection.getConnectionType(); if (hasLocalAndRemote && type == Connection.TYPE_LOCAL) { showSnackbar(R.string.info_conn_url); @@ -299,7 +290,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements mController.indicateServerCommunicationFailure( getString(R.string.error_empty_sitemap_list)); } else { - OpenHABSitemap sitemap = selectConfiguredSitemapFromList(); + Sitemap sitemap = selectConfiguredSitemapFromList(); if (sitemap != null) { openSitemap(sitemap); } else { @@ -316,11 +307,11 @@ public class OpenHABMainActivity extends AppCompatActivity implements Log.d(TAG, "Service resolved: " + serviceInfo.getHostAddresses()[0] + " port:" + serviceInfo.getPort()); - String openHABUrl = "https://" + serviceInfo.getHostAddresses()[0] + ":" + - String.valueOf(serviceInfo.getPort()) + "/"; + String serverUrl = "https://" + serviceInfo.getHostAddresses()[0] + ":" + + String.valueOf(serviceInfo.getPort()) + "/"; PreferenceManager.getDefaultSharedPreferences(this).edit() - .putString(Constants.PREFERENCE_LOCAL_URL, openHABUrl).apply(); + .putString(Constants.PREFERENCE_LOCAL_URL, serverUrl).apply(); // We'll get a connection update later mServiceResolver = null; } @@ -345,6 +336,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements CloudMessagingHelper.onNotificationSelected(this, intent); onNotificationSelected(intent); break; + default: + break; } } @@ -444,8 +437,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements } else if (failureReason != null) { final String message; if (failureReason instanceof NetworkNotSupportedException) { - NetworkInfo info = ((NetworkNotSupportedException) failureReason).getNetworkInfo(); - message = getString(R.string.error_network_type_unsupported, info.getTypeName()); + NetworkInfo info = + ((NetworkNotSupportedException) failureReason).getNetworkInfo(); + message = getString(R.string.error_network_type_unsupported, + info.getTypeName()); } else { message = getString(R.string.error_network_not_available); } @@ -496,8 +491,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements mServiceResolver.interrupt(); mServiceResolver = null; } - if (mSelectSitemapDialog != null && mSelectSitemapDialog.isShowing()) { - mSelectSitemapDialog.dismiss(); + if (mSitemapSelectionDialog != null && mSitemapSelectionDialog.isShowing()) { + mSitemapSelectionDialog.dismiss(); } if (mPropsUpdateHandle != null) { mPropsUpdateHandle.cancel(); @@ -509,8 +504,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements } private void setupToolbar() { - mToolbar = (Toolbar) findViewById(R.id.openhab_toolbar); - setSupportActionBar(mToolbar); + Toolbar toolbar = findViewById(R.id.openhab_toolbar); + setSupportActionBar(toolbar); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); @@ -518,8 +513,9 @@ public class OpenHABMainActivity extends AppCompatActivity implements // ProgressBar layout params inside the toolbar have to be done programmatically // because it doesn't work through layout file :-( - mProgressBar = (ProgressBar) mToolbar.findViewById(R.id.toolbar_progress_bar); - mProgressBar.setLayoutParams(new Toolbar.LayoutParams(Gravity.END | Gravity.CENTER_VERTICAL)); + mProgressBar = toolbar.findViewById(R.id.toolbar_progress_bar); + mProgressBar.setLayoutParams( + new Toolbar.LayoutParams(Gravity.END | Gravity.CENTER_VERTICAL)); setProgressIndicatorVisible(false); } @@ -532,9 +528,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements @Override public void onDrawerOpened(View drawerView) { if (mServerProperties != null && mPropsUpdateHandle == null) { - mPropsUpdateHandle = ServerProperties.updateSitemaps(mServerProperties, mConnection, + mPropsUpdateHandle = ServerProperties.updateSitemaps(mServerProperties, + mConnection, props -> { mServerProperties = props; updateSitemapDrawerItems(); }, - OpenHABMainActivity.this::handlePropertyFetchFailure); + MainActivity.this::handlePropertyFetchFailure); } } }); @@ -554,38 +551,38 @@ public class OpenHABMainActivity extends AppCompatActivity implements item.setIcon(applyDrawerIconTint(item.getIcon())); } - drawerMenu.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(@NonNull MenuItem item) { - mDrawerLayout.closeDrawers(); - switch (item.getItemId()) { - case R.id.notifications: - openNotifications(null); - return true; - case R.id.settings: - Intent settingsIntent = new Intent(OpenHABMainActivity.this, - OpenHABPreferencesActivity.class); - settingsIntent.putExtra(OpenHABPreferencesActivity.START_EXTRA_SERVER_PROPERTIES, - mServerProperties); - startActivityForResult(settingsIntent, SETTINGS_REQUEST_CODE); - return true; - case R.id.about: - openAbout(); - return true; - } - if (item.getGroupId() == GROUP_ID_SITEMAPS) { - OpenHABSitemap sitemap = mServerProperties.sitemaps().get(item.getItemId()); - openSitemap(sitemap); + drawerMenu.setNavigationItemSelectedListener(item -> { + mDrawerLayout.closeDrawers(); + switch (item.getItemId()) { + case R.id.notifications: + openNotifications(null); return true; - } - return false; + case R.id.settings: + Intent settingsIntent = new Intent(MainActivity.this, + PreferencesActivity.class); + settingsIntent.putExtra(PreferencesActivity.START_EXTRA_SERVER_PROPERTIES, + mServerProperties); + startActivityForResult(settingsIntent, SETTINGS_REQUEST_CODE); + return true; + case R.id.about: + openAbout(); + return true; + default: + break; + } + if (item.getGroupId() == GROUP_ID_SITEMAPS) { + Sitemap sitemap = mServerProperties.sitemaps().get(item.getItemId()); + openSitemap(sitemap); + return true; } + return false; }); } private void updateNotificationDrawerItem() { MenuItem notificationsItem = mDrawerMenu.findItem(R.id.notifications); - notificationsItem.setVisible(ConnectionFactory.getConnection(Connection.TYPE_CLOUD) != null); + notificationsItem.setVisible( + ConnectionFactory.getConnection(Connection.TYPE_CLOUD) != null); } private void updateSitemapDrawerItems() { @@ -594,8 +591,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements sitemapItem.setVisible(false); } else { final String defaultSitemapName = - mSettings.getString(Constants.PREFERENCE_SITEMAP_NAME, ""); - final List<OpenHABSitemap> sitemaps = mServerProperties.sitemaps(); + mPrefs.getString(Constants.PREFERENCE_SITEMAP_NAME, ""); + final List<Sitemap> sitemaps = mServerProperties.sitemaps(); Util.sortSitemapList(sitemaps, defaultSitemapName); if (sitemaps.isEmpty()) { @@ -606,7 +603,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements menu.clear(); for (int i = 0; i < sitemaps.size(); i++) { - OpenHABSitemap sitemap = sitemaps.get(i); + Sitemap sitemap = sitemaps.get(i); MenuItem item = menu.add(GROUP_ID_SITEMAPS, i, i, sitemap.label()); loadSitemapIcon(sitemap, item); } @@ -614,7 +611,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements } } - private void loadSitemapIcon(final OpenHABSitemap sitemap, final MenuItem item) { + private void loadSitemapIcon(final Sitemap sitemap, final MenuItem item) { final String url = sitemap.icon() != null ? Uri.encode(sitemap.iconPath(), "/?=") : null; Drawable defaultIcon = ContextCompat.getDrawable(this, R.drawable.ic_openhab_appicon_24dp); item.setIcon(applyDrawerIconTint(defaultIcon)); @@ -646,8 +643,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements } private void openNotificationsPageIfNeeded() { - if (mPendingOpenedNotificationId != null && mStarted && - ConnectionFactory.getConnection(Connection.TYPE_CLOUD) != null) { + if (mPendingOpenedNotificationId != null && mStarted + && ConnectionFactory.getConnection(Connection.TYPE_CLOUD) != null) { openNotifications(mPendingOpenedNotificationId); mPendingOpenedNotificationId = null; } @@ -688,12 +685,12 @@ public class OpenHABMainActivity extends AppCompatActivity implements Util.overridePendingTransition(this, false); } - private OpenHABSitemap selectConfiguredSitemapFromList() { + private Sitemap selectConfiguredSitemapFromList() { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); String configuredSitemap = settings.getString(Constants.PREFERENCE_SITEMAP_NAME, ""); - List<OpenHABSitemap> sitemaps = mServerProperties.sitemaps(); - final OpenHABSitemap result; + List<Sitemap> sitemaps = mServerProperties.sitemaps(); + final Sitemap result; if (sitemaps.size() == 1) { // We only have one sitemap, use it @@ -728,32 +725,29 @@ public class OpenHABMainActivity extends AppCompatActivity implements private void showSitemapSelectionDialog() { Log.d(TAG, "Opening sitemap selection dialog"); - if (mSelectSitemapDialog != null && mSelectSitemapDialog.isShowing()) { - mSelectSitemapDialog.dismiss(); + if (mSitemapSelectionDialog != null && mSitemapSelectionDialog.isShowing()) { + mSitemapSelectionDialog.dismiss(); } if (isFinishing()) { return; } - List<OpenHABSitemap> sitemaps = mServerProperties.sitemaps(); + List<Sitemap> sitemaps = mServerProperties.sitemaps(); final String[] sitemapLabels = new String[sitemaps.size()]; for (int i = 0; i < sitemaps.size(); i++) { sitemapLabels[i] = sitemaps.get(i).label(); } - mSelectSitemapDialog = new AlertDialog.Builder(this) + mSitemapSelectionDialog = new AlertDialog.Builder(this) .setTitle(R.string.mainmenu_openhab_selectsitemap) - .setItems(sitemapLabels, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int item) { - OpenHABSitemap sitemap = sitemaps.get(item); - Log.d(TAG, "Selected sitemap " + sitemap); - PreferenceManager.getDefaultSharedPreferences(OpenHABMainActivity.this) - .edit() - .putString(Constants.PREFERENCE_SITEMAP_NAME, sitemap.name()) - .putString(Constants.PREFERENCE_SITEMAP_LABEL, sitemap.label()) - .apply(); - openSitemap(sitemap); - } + .setItems(sitemapLabels, (dialog, which) -> { + Sitemap sitemap = sitemaps.get(which); + Log.d(TAG, "Selected sitemap " + sitemap); + PreferenceManager.getDefaultSharedPreferences(MainActivity.this) + .edit() + .putString(Constants.PREFERENCE_SITEMAP_NAME, sitemap.name()) + .putString(Constants.PREFERENCE_SITEMAP_LABEL, sitemap.label()) + .apply(); + openSitemap(sitemap); }) .show(); } @@ -763,7 +757,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements mDrawerToggle.setDrawerIndicatorEnabled(false); } - private void openSitemap(OpenHABSitemap sitemap) { + private void openSitemap(Sitemap sitemap) { Log.i(TAG, "Opening sitemap " + sitemap + ", currently selected " + mSelectedSitemap); if (mSelectedSitemap != null && mSelectedSitemap.equals(sitemap)) { return; @@ -784,10 +778,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements public boolean onPrepareOptionsMenu(Menu menu) { Log.d(TAG, "onPrepareOptionsMenu()"); MenuItem voiceRecognitionItem = menu.findItem(R.id.mainmenu_voice_recognition); + @ColorInt int iconColor = ContextCompat.getColor(this, R.color.light); voiceRecognitionItem.setVisible( mConnection != null && SpeechRecognizer.isRecognitionAvailable(this)); - voiceRecognitionItem.getIcon() - .setColorFilter(ContextCompat.getColor(this, R.color.light), PorterDuff.Mode.SRC_IN); + voiceRecognitionItem.getIcon().setColorFilter(iconColor, PorterDuff.Mode.SRC_IN); return true; } @@ -795,18 +789,18 @@ public class OpenHABMainActivity extends AppCompatActivity implements @Override public boolean onOptionsItemSelected(MenuItem item) { Log.d(TAG, "onOptionsItemSelected()"); - //clicking the back navigation arrow + // Handle back navigation arrow if (item.getItemId() == android.R.id.home && mController.canGoBack()) { mController.goBack(); return true; } - //clicking the hamburger menu + // Handle hamburger menu if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } - //menu items + // Handle menu items switch (item.getItemId()) { case R.id.mainmenu_voice_recognition: launchVoiceRecognition(); @@ -818,21 +812,22 @@ public class OpenHABMainActivity extends AppCompatActivity implements @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - Log.d(TAG, String.format("onActivityResult() requestCode = %d, resultCode = %d", requestCode, resultCode)); + Log.d(TAG, String.format("onActivityResult() requestCode = %d, resultCode = %d", + requestCode, resultCode)); switch (requestCode) { case SETTINGS_REQUEST_CODE: if (data == null) { break; } - if (data.getBooleanExtra(OpenHABPreferencesActivity.RESULT_EXTRA_SITEMAP_CLEARED, false)) { - OpenHABSitemap sitemap = selectConfiguredSitemapFromList(); + if (data.getBooleanExtra(PreferencesActivity.RESULT_EXTRA_SITEMAP_CLEARED, false)) { + Sitemap sitemap = selectConfiguredSitemapFromList(); if (sitemap != null) { openSitemap(sitemap); } else { showSitemapSelectionDialog(); } } - if (data.getBooleanExtra(OpenHABPreferencesActivity.RESULT_EXTRA_THEME_CHANGED, false)) { + if (data.getBooleanExtra(PreferencesActivity.RESULT_EXTRA_THEME_CHANGED, false)) { recreate(); } break; @@ -851,8 +846,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements mStarted = false; savedInstanceState.putParcelable("serverProperties", mServerProperties); savedInstanceState.putParcelable("sitemap", mSelectedSitemap); - savedInstanceState.putBoolean("isSitemapSelectionDialogShown", mSelectSitemapDialog != null && - mSelectSitemapDialog.isShowing()); + savedInstanceState.putBoolean("isSitemapSelectionDialogShown", + mSitemapSelectionDialog != null && mSitemapSelectionDialog.isShowing()); savedInstanceState.putString("controller", mController.getClass().getCanonicalName()); savedInstanceState.putInt("connectionHash", mConnection != null ? mConnection.hashCode() : -1); @@ -871,7 +866,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements openNotificationsPageIfNeeded(); } - public void onWidgetSelected(OpenHABLinkedPage linkedPage, OpenHABWidgetListFragment source) { + public void onWidgetSelected(LinkedPage linkedPage, WidgetListFragment source) { Log.d(TAG, "Got widget link = " + linkedPage.link()); mController.openPage(linkedPage, source); } @@ -887,7 +882,9 @@ public class OpenHABMainActivity extends AppCompatActivity implements Log.d(TAG, "onBackPressed()"); if (mController.canGoBack()) { mController.goBack(); - } else if (!isFullscreenEnabled()) { //in fullscreen don't continue back which would exit the app + } else if (!isFullscreenEnabled()) { + // Only handle back action in non-fullscreen mode, as we don't want to exit + // the app via back button in fullscreen mode super.onBackPressed(); } } @@ -903,13 +900,14 @@ public class OpenHABMainActivity extends AppCompatActivity implements } private void launchVoiceRecognition() { - Intent callbackIntent = new Intent(this, OpenHABVoiceService.class); + Intent callbackIntent = new Intent(this, VoiceService.class); PendingIntent openhabPendingIntent = PendingIntent.getService(this, 0, callbackIntent, 0); Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); // Display an hint to the user about what he should say. speechIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.info_voice_input)); - speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); speechIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, openhabPendingIntent); @@ -934,13 +932,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements mLastSnackbar = Snackbar.make(findViewById(android.R.id.content), R.string.swipe_to_refresh_description, Snackbar.LENGTH_LONG); - mLastSnackbar.setAction(R.string.swipe_to_refresh_dismiss, new View.OnClickListener() { - @Override - public void onClick(View v) { - prefs.edit() - .putBoolean(Constants.PREFERENCE_SWIPE_REFRESH_EXPLAINED, true) - .apply(); - } + mLastSnackbar.setAction(R.string.swipe_to_refresh_dismiss, v -> { + prefs.edit() + .putBoolean(Constants.PREFERENCE_SWIPE_REFRESH_EXPLAINED, true) + .apply(); }); mLastSnackbar.show(); } @@ -962,16 +957,18 @@ public class OpenHABMainActivity extends AppCompatActivity implements Log.e(TAG, "Error: " + error.toString()); Log.e(TAG, "HTTP status code: " + statusCode); CharSequence message; - if (statusCode >= 400){ + if (statusCode >= 400) { if (error.getMessage().equals("openHAB is offline")) { message = getString(R.string.error_openhab_offline); } else { - int resourceID; + int resourceId; try { - resourceID = getResources().getIdentifier("error_http_code_" + statusCode, "string", getPackageName()); - message = getString(resourceID); - } catch (android.content.res.Resources.NotFoundException e) { - message = String.format(getString(R.string.error_http_connection_failed), statusCode); + resourceId = getResources().getIdentifier( + "error_http_code_" + statusCode, + "string", getPackageName()); + message = getString(resourceId); + } catch (Resources.NotFoundException e) { + message = getString(R.string.error_http_connection_failed, statusCode); } } } else if (error instanceof UnknownHostException) { @@ -1002,7 +999,7 @@ public class OpenHABMainActivity extends AppCompatActivity implements } SharedPreferences settings = - PreferenceManager.getDefaultSharedPreferences(OpenHABMainActivity.this); + PreferenceManager.getDefaultSharedPreferences(MainActivity.this); if (settings.getBoolean(Constants.PREFERENCE_DEBUG_MESSAGES, false)) { SpannableStringBuilder builder = new SpannableStringBuilder(message); int detailsStart = builder.length(); @@ -1014,7 +1011,8 @@ public class OpenHABMainActivity extends AppCompatActivity implements String base64Credentials = authHeader.substring("Basic".length()).trim(); String credentials = new String(Base64.decode(base64Credentials, Base64.DEFAULT), Charset.forName("UTF-8")); - builder.append("\nUsername: ").append(credentials.substring(0, credentials.indexOf(":"))); + builder.append("\nUsername: ") + .append(credentials.substring(0, credentials.indexOf(":"))); } builder.append("\nException stack:\n"); @@ -1058,12 +1056,10 @@ public class OpenHABMainActivity extends AppCompatActivity implements */ protected void checkFullscreen() { if (isFullscreenEnabled()) { - int uiOptions = getWindow().getDecorView().getSystemUiVisibility(); - uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN; - } + int uiOptions = getWindow().getDecorView().getSystemUiVisibility() + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_FULLSCREEN; getWindow().getDecorView().setSystemUiVisibility(uiOptions); } } @@ -1072,8 +1068,9 @@ public class OpenHABMainActivity extends AppCompatActivity implements * If we are 4.4 we can use fullscreen mode and Daydream features */ protected boolean isFullscreenEnabled() { - boolean supportsKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - boolean fullScreen = mSettings.getBoolean("default_openhab_fullscreen", false); - return supportsKitKat && fullScreen; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + return false; + } + return mPrefs.getBoolean(Constants.PREFERENCE_FULLSCREEN, false); } } \ No newline at end of file diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABPreferencesActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/PreferencesActivity.java similarity index 72% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABPreferencesActivity.java rename to mobile/src/main/java/org/openhab/habdroid/ui/PreferencesActivity.java index fe8cb455685d04da872962359dd3130bbb6a5ab3..eb737fa0421517bfea49879b46a4b8d16ff9220e 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABPreferencesActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/PreferencesActivity.java @@ -19,7 +19,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; @@ -50,13 +49,13 @@ import static org.openhab.habdroid.util.Util.getHostFromUrl; /** * This is a class to provide preferences activity for application. */ -public class OpenHABPreferencesActivity extends AppCompatActivity { +public class PreferencesActivity extends AppCompatActivity { public static final String RESULT_EXTRA_THEME_CHANGED = "theme_changed"; public static final String RESULT_EXTRA_SITEMAP_CLEARED = "sitemap_cleared"; public static final String START_EXTRA_SERVER_PROPERTIES = "server_properties"; private static final String STATE_KEY_RESULT = "result"; - private static final String TAG = OpenHABPreferencesActivity.class.getSimpleName(); + private static final String TAG = PreferencesActivity.class.getSimpleName(); private Intent mResultIntent; @Override @@ -66,7 +65,7 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { setContentView(R.layout.activity_prefs); - Toolbar toolbar = (Toolbar) findViewById(R.id.openhab_toolbar); + Toolbar toolbar = findViewById(R.id.openhab_toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -99,8 +98,9 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { NavUtils.navigateUpFromSameTask(this); } return true; + default: + return super.onOptionsItemSelected(item); } - return super.onOptionsItemSelected(item); } @Override @@ -123,7 +123,7 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { } @VisibleForTesting - public static abstract class AbstractSettingsFragment extends PreferenceFragment { + public abstract static class AbstractSettingsFragment extends PreferenceFragment { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -140,8 +140,8 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { protected abstract @StringRes int getTitleResId(); - protected OpenHABPreferencesActivity getParentActivity() { - return (OpenHABPreferencesActivity) getActivity(); + protected PreferencesActivity getParentActivity() { + return (PreferencesActivity) getActivity(); } protected String getPreferenceString(Preference preference, String defValue) { @@ -165,8 +165,10 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { } protected boolean isConnectionSecure(String url, String user, String password) { - return isConnectionHttps(url) && - (hasConnectionBasicAuthentication(user, password) || hasClientCertificate()); + if (!isConnectionHttps(url)) { + return false; + } + return hasConnectionBasicAuthentication(user, password) || hasClientCertificate(); } @@ -223,25 +225,23 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { protected void updateAndInitPreferences() { addPreferencesFromResource(R.xml.preferences); - final Preference subScreenLocalConn = findPreference(Constants.SUBSCREEN_LOCAL_CONNECTION); - final Preference subScreenRemoteConn = findPreference(Constants.SUBSCREEN_REMOTE_CONNECTION); - final Preference themePreference = getPreferenceScreen().findPreference(Constants.PREFERENCE_THEME); - final Preference clearCachePreference = getPreferenceScreen().findPreference(Constants - .PREFERENCE_CLEAR_CACHE); - final Preference clearDefaultSitemapPreference = getPreferenceScreen().findPreference - (Constants.PREFERENCE_CLEAR_DEFAULT_SITEMAP); - final Preference ringtonePreference = getPreferenceScreen().findPreference(Constants.PREFERENCE_TONE); - final Preference vibrationPreference = - getPreferenceScreen().findPreference(Constants.PREFERENCE_NOTIFICATION_VIBRATION); - - String currentDefaultSitemap = clearDefaultSitemapPreference.getSharedPreferences().getString(Constants - .PREFERENCE_SITEMAP_NAME, ""); - String currentDefaultSitemapLabel = clearDefaultSitemapPreference.getSharedPreferences().getString(Constants - .PREFERENCE_SITEMAP_LABEL, ""); + final Preference localConnPref = findPreference(Constants.SUBSCREEN_LOCAL_CONNECTION); + final Preference remoteConnPref = findPreference(Constants.SUBSCREEN_REMOTE_CONNECTION); + final Preference themePref = findPreference(Constants.PREFERENCE_THEME); + final Preference clearCachePref = findPreference(Constants.PREFERENCE_CLEAR_CACHE); + final Preference clearDefaultSitemapPref = + findPreference(Constants.PREFERENCE_CLEAR_DEFAULT_SITEMAP); + final Preference ringtonePref = findPreference(Constants.PREFERENCE_TONE); + final Preference vibrationPref = + findPreference(Constants.PREFERENCE_NOTIFICATION_VIBRATION); + final SharedPreferences prefs = getPreferenceScreen().getSharedPreferences(); + + String currentDefaultSitemap = prefs.getString(Constants.PREFERENCE_SITEMAP_NAME, ""); + String currentDefaultSitemapLabel = prefs.getString(Constants.PREFERENCE_SITEMAP_LABEL, ""); if (currentDefaultSitemap.isEmpty()) { - onNoDefaultSitemap(clearDefaultSitemapPreference); + onNoDefaultSitemap(clearDefaultSitemapPref); } else { - clearDefaultSitemapPreference.setSummary(getString( + clearDefaultSitemapPref.setSummary(getString( R.string.settings_current_default_sitemap, currentDefaultSitemapLabel)); } @@ -251,80 +251,59 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { updateConnectionSummary(Constants.SUBSCREEN_REMOTE_CONNECTION, Constants.PREFERENCE_REMOTE_URL, Constants.PREFERENCE_REMOTE_USERNAME, Constants.PREFERENCE_REMOTE_PASSWORD); - updateRingtonePreferenceSummary(ringtonePreference, ringtonePreference - .getSharedPreferences().getString(Constants.PREFERENCE_TONE, "")); - updateVibrationPreferenceIcon(vibrationPreference, vibrationPreference - .getSharedPreferences().getString(Constants.PREFERENCE_NOTIFICATION_VIBRATION, "")); - - subScreenLocalConn.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - getParentActivity().openSubScreen(new LocalConnectionSettingsFragment()); - return false; - } + updateRingtonePreferenceSummary(ringtonePref, + prefs.getString(Constants.PREFERENCE_TONE, "")); + updateVibrationPreferenceIcon(vibrationPref, + prefs.getString(Constants.PREFERENCE_NOTIFICATION_VIBRATION, "")); + + localConnPref.setOnPreferenceClickListener(preference -> { + getParentActivity().openSubScreen(new LocalConnectionSettingsFragment()); + return false; }); - subScreenRemoteConn.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - getParentActivity().openSubScreen(new RemoteConnectionSettingsFragment()); - return false; - } + remoteConnPref.setOnPreferenceClickListener(preference -> { + getParentActivity().openSubScreen(new RemoteConnectionSettingsFragment()); + return false; }); - themePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - getParentActivity().handleThemeChange(); - return true; - } + themePref.setOnPreferenceChangeListener((preference, newValue) -> { + getParentActivity().handleThemeChange(); + return true; }); - clearCachePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - // Get launch intent for application - Intent restartIntent = getActivity().getPackageManager() - .getLaunchIntentForPackage(getActivity().getBaseContext().getPackageName()); - restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - // Finish current activity - getActivity().finish(); - CacheManager.getInstance(getActivity()).clearCache(); - // Start launch activity - startActivity(restartIntent); - // Start launch activity - return true; - } + clearCachePref.setOnPreferenceClickListener(preference -> { + // Get launch intent for application + Intent restartIntent = getActivity().getPackageManager() + .getLaunchIntentForPackage(getActivity().getBaseContext().getPackageName()); + restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + // Finish current activity + getActivity().finish(); + CacheManager.getInstance(getActivity()).clearCache(); + // Start launch activity + startActivity(restartIntent); + // Start launch activity + return true; }); - clearDefaultSitemapPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - SharedPreferences.Editor edit = preference.getSharedPreferences().edit(); - edit.putString(Constants.PREFERENCE_SITEMAP_NAME, ""); - edit.putString(Constants.PREFERENCE_SITEMAP_LABEL, ""); - edit.apply(); - - onNoDefaultSitemap(preference); - getParentActivity().mResultIntent.putExtra(RESULT_EXTRA_SITEMAP_CLEARED, true); - return true; - } + clearDefaultSitemapPref.setOnPreferenceClickListener(preference -> { + SharedPreferences.Editor edit = preference.getSharedPreferences().edit(); + edit.putString(Constants.PREFERENCE_SITEMAP_NAME, ""); + edit.putString(Constants.PREFERENCE_SITEMAP_LABEL, ""); + edit.apply(); + + onNoDefaultSitemap(preference); + getParentActivity().mResultIntent.putExtra(RESULT_EXTRA_SITEMAP_CLEARED, true); + return true; }); - ringtonePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - updateRingtonePreferenceSummary(preference, newValue); - return true; - } + ringtonePref.setOnPreferenceChangeListener((pref, newValue) -> { + updateRingtonePreferenceSummary(pref, newValue); + return true; }); - vibrationPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - updateVibrationPreferenceIcon(preference, newValue); - return true; - } + vibrationPref.setOnPreferenceChangeListener((pref, newValue) -> { + updateVibrationPreferenceIcon(pref, newValue); + return true; }); final PreferenceScreen ps = getPreferenceScreen(); @@ -337,18 +316,20 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { if (!CloudMessagingHelper.isSupported()) { Log.d(TAG, "Removing full-only prefs"); - getParent(ringtonePreference).removePreference(ringtonePreference); - getParent(vibrationPreference).removePreference(vibrationPreference); + getParent(ringtonePref).removePreference(ringtonePref); + getParent(vibrationPref).removePreference(vibrationPref); } - ServerProperties props = + final ServerProperties props = getActivity().getIntent().getParcelableExtra(START_EXTRA_SERVER_PROPERTIES); - if (props != null && (props.flags() & ServerProperties.SERVER_FLAG_ICON_FORMAT_SUPPORT) == 0) { + final int flags = props != null ? props.flags() : 0; + + if ((flags & ServerProperties.SERVER_FLAG_ICON_FORMAT_SUPPORT) == 0) { Preference iconFormatPreference = ps.findPreference(Constants.PREFERENCE_ICON_FORMAT); getParent(iconFormatPreference).removePreference(iconFormatPreference); } - if (props != null && (props.flags() & ServerProperties.SERVER_FLAG_CHART_SCALING_SUPPORT) == 0) { + if ((flags & ServerProperties.SERVER_FLAG_CHART_SCALING_SUPPORT) == 0) { Preference chartScalingPreference = ps.findPreference(Constants.PREFERENCE_CHART_SCALING); getParent(chartScalingPreference).removePreference(chartScalingPreference); @@ -408,7 +389,7 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { } private void updateConnectionSummary(String subscreenPrefKey, String urlPrefKey, - String userPrefKey, String passwordPrefKey) { + String userPrefKey, String passwordPrefKey) { Preference pref = findPreference(subscreenPrefKey); String url = getPreferenceString(urlPrefKey, ""); final String summary; @@ -430,7 +411,7 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { } } - private static abstract class ConnectionSettingsFragment extends AbstractSettingsFragment { + private abstract static class ConnectionSettingsFragment extends AbstractSettingsFragment { private Preference mUrlPreference; private Preference mUserNamePreference; private Preference mPasswordPreference; @@ -438,21 +419,22 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { private interface IconColorGenerator { Integer getIconColor(); } + private interface PrefSummaryGenerator { CharSequence getSummary(String value); } protected void initPreferences(String urlPrefKey, String userNamePrefKey, String passwordPrefKey, @StringRes int urlSummaryFormatResId) { - mUrlPreference = initEditorPreference(urlPrefKey, R.drawable.ic_earth_grey_24dp, value -> { + mUrlPreference = initEditor(urlPrefKey, R.drawable.ic_earth_grey_24dp, value -> { if (TextUtils.isEmpty(value)) { return getString(R.string.info_not_set); } return getString(urlSummaryFormatResId, value); }); - mUserNamePreference = initEditorPreference(userNamePrefKey, R.drawable.ic_person_grey_24dp, + mUserNamePreference = initEditor(userNamePrefKey, R.drawable.ic_person_grey_24dp, value -> TextUtils.isEmpty(value) ? getString(R.string.info_not_set) : value); - mPasswordPreference = initEditorPreference(passwordPrefKey, + mPasswordPreference = initEditor(passwordPrefKey, R.drawable.ic_security_grey_24dp, value -> { @StringRes int resId = TextUtils.isEmpty(value) ? R.string.info_not_set : isWeakPassword(value) ? R.string.settings_openhab_password_summary_weak @@ -465,7 +447,7 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { getPreferenceString(passwordPrefKey, "")); } - private Preference initEditorPreference(String key, @DrawableRes int iconResId, + private Preference initEditor(String key, @DrawableRes int iconResId, PrefSummaryGenerator summaryGenerator) { Preference preference = getPreferenceScreen().findPreference(key); preference.setIcon(DrawableCompat.wrap( @@ -494,7 +476,8 @@ public class OpenHABPreferencesActivity extends AppCompatActivity { }); updateIconColor(mUserNamePreference, () -> { if (!TextUtils.isEmpty(url)) { - return TextUtils.isEmpty(userName) ? R.color.pref_icon_red : R.color.pref_icon_green; + return TextUtils.isEmpty(userName) + ? R.color.pref_icon_red : R.color.pref_icon_green; } return null; }); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/VoiceWidget.java b/mobile/src/main/java/org/openhab/habdroid/ui/VoiceWidget.java index d4b7680603da62d6be11b636e06724add9e512f4..0b7707fcc200e32a6cb2ad6b8fe7e38c9b1f0ee4 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/VoiceWidget.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/VoiceWidget.java @@ -18,13 +18,12 @@ import android.speech.RecognizerIntent; import android.widget.RemoteViews; import org.openhab.habdroid.R; -import org.openhab.habdroid.core.OpenHABVoiceService; +import org.openhab.habdroid.core.VoiceService; /** * Implementation of App Widget functionality. */ public class VoiceWidget extends AppWidgetProvider { - @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // There may be multiple widgets active, so update all of them @@ -43,27 +42,29 @@ public class VoiceWidget extends AppWidgetProvider { // Enter relevant functionality for when the last widget is disabled } - private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, - int appWidgetId) { + private void updateAppWidget(Context context, + AppWidgetManager appWidgetManager, int appWidgetId) { // Construct the RemoteViews object RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.voice_widget); - Intent callbackIntent = new Intent(context, OpenHABVoiceService.class); - PendingIntent openhabPendingIntent = PendingIntent.getService(context, 9, callbackIntent, 0); + Intent callbackIntent = new Intent(context, VoiceService.class); + PendingIntent callbackPendingIntent = PendingIntent.getService(context, + 9, callbackIntent, 0); Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); // Display an hint to the user about what he should say. - speechIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, context.getString(R.string.info_voice_input)); - speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + speechIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, + context.getString(R.string.info_voice_input)); + speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1); speechIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - speechIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, openhabPendingIntent); + speechIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, callbackPendingIntent); PendingIntent speechPendingIntent = PendingIntent.getActivity(context, 6, speechIntent, 0); - views.setOnClickPendingIntent(R.id.btn_mic, speechPendingIntent); - Intent mainIntent = new Intent(context, OpenHABMainActivity.class); + Intent mainIntent = new Intent(context, MainActivity.class); PendingIntent mainPendingIntent = PendingIntent.getActivity(context, 8, mainIntent, 0); views.setOnClickPendingIntent(R.id.btn_open_main, mainPendingIntent); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetAdapter.java b/mobile/src/main/java/org/openhab/habdroid/ui/WidgetAdapter.java similarity index 89% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetAdapter.java rename to mobile/src/main/java/org/openhab/habdroid/ui/WidgetAdapter.java index b514380b8d106e70e1bc5f3aecf61576a0e0b22d..dae4c587b69e4d040c522f14c96f4a3c0ab644c9 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetAdapter.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/WidgetAdapter.java @@ -11,7 +11,6 @@ package org.openhab.habdroid.ui; import android.annotation.SuppressLint; import android.content.Context; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -25,6 +24,7 @@ import android.os.Message; import android.preference.PreferenceManager; import android.support.annotation.IdRes; import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.support.v7.app.AlertDialog; import android.support.v7.widget.RecyclerView; @@ -40,7 +40,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.WebView; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageButton; import android.widget.ImageView; @@ -54,11 +53,13 @@ import com.larswerkman.holocolorpicker.ColorPicker; import com.larswerkman.holocolorpicker.SaturationBar; import com.larswerkman.holocolorpicker.ValueBar; +import okhttp3.HttpUrl; + import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; -import org.openhab.habdroid.model.OpenHABItem; -import org.openhab.habdroid.model.OpenHABLabeledValue; -import org.openhab.habdroid.model.OpenHABWidget; +import org.openhab.habdroid.model.Item; +import org.openhab.habdroid.model.LabeledValue; +import org.openhab.habdroid.model.Widget; import org.openhab.habdroid.ui.widget.DividerItemDecoration; import org.openhab.habdroid.ui.widget.ExtendedSpinner; import org.openhab.habdroid.ui.widget.SegmentedControlButton; @@ -69,26 +70,23 @@ import org.openhab.habdroid.util.Util; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; -import okhttp3.HttpUrl; - /** * This class provides openHAB widgets adapter for list view. */ -public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdapter.ViewHolder> +public class WidgetAdapter extends RecyclerView.Adapter<WidgetAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener { - private static final String TAG = "OpenHABWidgetAdapter"; + private static final String TAG = "WidgetAdapter"; public interface ItemClickListener { - void onItemClicked(OpenHABWidget item); - void onItemLongClicked(OpenHABWidget item); + void onItemClicked(Widget item); + void onItemLongClicked(Widget item); } private static final int TYPE_GENERICITEM = 0; @@ -109,7 +107,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap private static final int TYPE_VIDEO_MJPEG = 15; private static final int TYPE_LOCATION = 16; - private final ArrayList<OpenHABWidget> mItems = new ArrayList<>(); + private final ArrayList<Widget> mItems = new ArrayList<>(); private final LayoutInflater mInflater; private ItemClickListener mItemClickListener; private CharSequence mChartTheme; @@ -117,7 +115,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap private Connection mConnection; private ColorMapper mColorMapper; - public OpenHABWidgetAdapter(Context context, Connection connection, + public WidgetAdapter(Context context, Connection connection, ItemClickListener itemClickListener) { super(); @@ -131,7 +129,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap mChartTheme = tv.string; } - public void update(List<OpenHABWidget> widgets, boolean forceFullUpdate) { + public void update(List<Widget> widgets, boolean forceFullUpdate) { boolean compatibleUpdate = true; if (widgets.size() != mItems.size() || forceFullUpdate) { @@ -159,7 +157,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } } - public void updateWidget(OpenHABWidget widget) { + public void updateWidget(Widget widget) { for (int i = 0; i < mItems.size(); i++) { if (mItems.get(i).id().equals(widget.id())) { mItems.set(i, widget); @@ -169,6 +167,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } } + @NonNull @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final ViewHolder holder; @@ -207,7 +206,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap holder = new SetpointViewHolder(mInflater, parent, mConnection, mColorMapper); break; case TYPE_CHART: - holder = new ChartViewHolder(mInflater, parent, mChartTheme, mConnection, mColorMapper); + holder = new ChartViewHolder(mInflater, parent, + mChartTheme, mConnection, mColorMapper); break; case TYPE_VIDEO: holder = new VideoViewHolder(mInflater, parent, mConnection, mColorMapper); @@ -222,7 +222,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap holder = new MjpegVideoViewHolder(mInflater, parent, mConnection, mColorMapper); break; case TYPE_LOCATION: - holder = MapViewHelper.createViewHolder(mInflater, parent, mConnection, mColorMapper); + holder = MapViewHelper.createViewHolder(mInflater, parent, + mConnection, mColorMapper); break; default: throw new IllegalArgumentException("View type " + viewType + " is not known"); @@ -263,7 +264,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap return mItems.size(); } - public OpenHABWidget getItem(int position) { + public Widget getItem(int position) { return mItems.get(position); } @@ -272,7 +273,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap return getItemViewType(mItems.get(position)); } - private int getItemViewType(OpenHABWidget widget) { + private int getItemViewType(Widget widget) { switch (widget.type()) { case Frame: return TYPE_FRAME; @@ -282,8 +283,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap if (widget.hasMappings()) { return TYPE_SECTIONSWITCH; } else { - OpenHABItem item = widget.item(); - if (item != null && item.isOfTypeOrGroupType(OpenHABItem.Type.Rollershutter)) { + Item item = widget.item(); + if (item != null && item.isOfTypeOrGroupType(Item.Type.Rollershutter)) { return TYPE_ROLLERSHUTTER; } return TYPE_SWITCH; @@ -360,7 +361,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap mColorMapper = colorMapper; } - public abstract void bind(OpenHABWidget widget); + public abstract void bind(Widget widget); public void start() {} public void stop() {} @@ -378,7 +379,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } } - protected void updateIcon(WidgetImageView iconView, OpenHABWidget widget) { + protected void updateIcon(WidgetImageView iconView, Widget widget) { if (widget.icon() == null) { iconView.setImageDrawable(null); return; @@ -395,7 +396,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } } - public static abstract class LabeledItemBaseViewHolder extends ViewHolder { + public abstract static class LabeledItemBaseViewHolder extends ViewHolder { protected final TextView mLabelView; protected final TextView mValueView; protected final WidgetImageView mIconView; @@ -409,7 +410,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { String[] splitString = widget.label().split("\\[|\\]"); mLabelView.setText(splitString.length > 0 ? splitString[0] : null); updateTextViewColor(mLabelView, widget.labelColor()); @@ -434,7 +435,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { mLabelView.setText(widget.label()); updateTextViewColor(mLabelView, widget.labelColor()); updateIcon(mIconView, widget); @@ -456,7 +457,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { mLabelView.setText(widget.label()); updateTextViewColor(mLabelView, widget.valueColor()); // hide empty frames @@ -479,7 +480,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mRightArrow.setVisibility(widget.linkedPage() != null ? View.VISIBLE : View.GONE); } @@ -488,7 +489,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public static class SwitchViewHolder extends LabeledItemBaseViewHolder implements View.OnTouchListener { private final SwitchCompat mSwitch; - private OpenHABItem mBoundItem; + private Item mBoundItem; SwitchViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { @@ -498,7 +499,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); mSwitch.setChecked(mBoundItem != null && mBoundItem.stateAsBoolean()); @@ -524,7 +525,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mRightArrow.setVisibility(widget.linkedPage() != null ? View.VISIBLE : View.GONE); } @@ -533,7 +534,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public static class SliderViewHolder extends LabeledItemBaseViewHolder implements SeekBar.OnSeekBarChangeListener { private final SeekBar mSeekBar; - private OpenHABItem mBoundItem; + private Item mBoundItem; SliderViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { @@ -543,12 +544,12 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); if (mBoundItem != null) { int progress; - if (mBoundItem.isOfTypeOrGroupType(OpenHABItem.Type.Color)) { + if (mBoundItem.isOfTypeOrGroupType(Item.Type.Color)) { Integer brightness = mBoundItem.stateAsBrightness(); progress = brightness != null ? brightness : 0; } else { @@ -590,8 +591,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { - OpenHABItem item = widget.item(); + public void bind(Widget widget) { + Item item = widget.item(); final String state = item != null ? item.state() : null; // Make sure images fit into the content frame by scaling @@ -601,7 +602,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap mImageView.setMaxHeight(maxHeight); if (state != null && state.matches("data:image/.*;base64,.*")) { - byte[] data = Base64.decode(state.substring(state.indexOf(",") + 1), Base64.DEFAULT); + final String dataString = state.substring(state.indexOf(",") + 1); + byte[] data = Base64.decode(dataString, Base64.DEFAULT); Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); mImageView.setImageBitmap(bitmap); mRefreshRate = 0; @@ -629,8 +631,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public static class SelectionViewHolder extends LabeledItemBaseViewHolder implements ExtendedSpinner.OnSelectionUpdatedListener { private final ExtendedSpinner mSpinner; - private OpenHABItem mBoundItem; - private List<OpenHABLabeledValue> mBoundMappings; + private Item mBoundItem; + private List<LabeledValue> mBoundMappings; SelectionViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { @@ -640,7 +642,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); @@ -650,7 +652,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap ArrayList<String> spinnerArray = new ArrayList<>(); String state = mBoundItem != null ? mBoundItem.state() : null; - for (OpenHABLabeledValue mapping : mBoundMappings) { + for (LabeledValue mapping : mBoundMappings) { String command = mapping.value(); spinnerArray.add(mapping.label()); if (command != null && command.equals(state)) { @@ -662,7 +664,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap spinnerSelectedIndex = spinnerArray.size() - 1; } - ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(itemView.getContext(), + ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(itemView.getContext(), android.R.layout.simple_spinner_item, spinnerArray); spinnerAdapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice); @@ -677,7 +679,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap if (position >= mBoundMappings.size()) { return; } - OpenHABLabeledValue item = mBoundMappings.get(position); + LabeledValue item = mBoundMappings.get(position); Log.d(TAG, "Spinner onItemSelected found match with " + item.value()); Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, item.value()); } @@ -687,21 +689,22 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap implements View.OnClickListener { private final LayoutInflater mInflater; private final RadioGroup mRadioGroup; - private OpenHABItem mBoundItem; + private Item mBoundItem; SectionSwitchViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { - super(inflater, parent, R.layout.openhabwidgetlist_sectionswitchitem, conn, colorMapper); + super(inflater, parent, + R.layout.openhabwidgetlist_sectionswitchitem, conn, colorMapper); mInflater = inflater; mRadioGroup = itemView.findViewById(R.id.switchgroup); } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); - List<OpenHABLabeledValue> mappings = widget.mappings(); + List<LabeledValue> mappings = widget.mappings(); // inflate missing views for (int i = mRadioGroup.getChildCount(); i < mappings.size(); i++) { View view = mInflater.inflate(R.layout.openhabwidgetlist_sectionswitchitem_button, @@ -727,17 +730,19 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap @Override public void onClick(View view) { - Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, (String) view.getTag()); + final String cmd = (String) view.getTag(); + Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, cmd); } } public static class RollerShutterViewHolder extends LabeledItemBaseViewHolder implements View.OnTouchListener { - private OpenHABItem mBoundItem; + private Item mBoundItem; RollerShutterViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { - super(inflater, parent, R.layout.openhabwidgetlist_rollershutteritem, conn, colorMapper); + super(inflater, parent, + R.layout.openhabwidgetlist_rollershutteritem, conn, colorMapper); initButton(R.id.up_button, "UP"); initButton(R.id.down_button, "DOWN"); initButton(R.id.stop_button, "STOP"); @@ -750,7 +755,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); } @@ -758,7 +763,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap @Override public boolean onTouch(View v, MotionEvent motionEvent) { if (motionEvent.getActionMasked() == MotionEvent.ACTION_UP) { - Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, (String) v.getTag()); + final String cmd = (String) v.getTag(); + Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, cmd); } return false; } @@ -767,7 +773,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public static class SetpointViewHolder extends LabeledItemBaseViewHolder implements View.OnClickListener { private final LayoutInflater mInflater; - private OpenHABWidget mBoundWidget; + private Widget mBoundWidget; SetpointViewHolder(LayoutInflater inflater, ViewGroup parent, Connection conn, ColorMapper colorMapper) { @@ -780,7 +786,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundWidget = widget; } @@ -789,14 +795,15 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public void onClick(final View view) { float minValue = mBoundWidget.minValue(); float maxValue = mBoundWidget.maxValue(); - //This prevents an exception below. But could lead to user confusion if this case is ever encountered. + // This prevents an exception below, but could lead to + // user confusion if this case is ever encountered. float stepSize = minValue == maxValue ? 1 : mBoundWidget.step(); - - final String[] stepValues = new String[((int) (Math.abs(maxValue - minValue) / stepSize)) + 1]; + final int stepCount = ((int) (Math.abs(maxValue - minValue) / stepSize)) + 1; + final String[] stepValues = new String[stepCount]; for (int i = 0; i < stepValues.length; i++) { - //Check if step size is a whole integer. + // Check if step size is a whole integer. if (stepSize == Math.ceil(stepSize)) { - //Cast to int to prevent .0 being added to all values in picker + // Cast to int to prevent .0 being added to all values in picker stepValues[i] = String.valueOf((int) (minValue + (i * stepSize))); } else { stepValues[i] = String.valueOf(minValue + (i * stepSize)); @@ -812,27 +819,23 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap // Find the closest value in the calculated step value String stateString = Float.toString(mBoundWidget.item().stateAsFloat()); - int stepIndex = Arrays.binarySearch(stepValues, stateString, new Comparator<CharSequence>() { - @Override - public int compare(CharSequence t1, CharSequence t2) { - return Float.valueOf(t1.toString()).compareTo(Float.valueOf(t2.toString())); - } - }); + int stepIndex = Arrays.binarySearch(stepValues, stateString, + (lhs, rhs) -> Float.valueOf(lhs).compareTo(Float.valueOf(rhs))); if (stepIndex < 0) { - stepIndex = (-(stepIndex + 1)); // Use the returned insertion point if value is not found and select the closest value. - stepIndex = Math.min(stepIndex, stepValues.length - 1); //handle case where insertion would be larger than the array + // Use the returned insertion point if value is not + // found and select the closest value. + stepIndex = -(stepIndex + 1); + // Handle case where insertion would be larger than the array + stepIndex = Math.min(stepIndex, stepValues.length - 1); } numberPicker.setValue(stepIndex); new AlertDialog.Builder(view.getContext()) .setTitle(mLabelView.getText()) .setView(dialogView) - .setPositiveButton(R.string.set, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundWidget.item(), - stepValues[numberPicker.getValue()]); - } + .setPositiveButton(R.string.set, (dialog, which) -> { + Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundWidget.item(), + stepValues[numberPicker.getValue()]); }) .setNegativeButton(R.string.cancel, null) .show(); @@ -854,25 +857,26 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap mImageView = itemView.findViewById(R.id.chart); mParentView = parent; - WindowManager wm = (WindowManager) itemView.getContext().getSystemService(Context.WINDOW_SERVICE); + final Context context = itemView.getContext(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics metrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); mDensity = metrics.densityDpi; mChartTheme = theme; - mPrefs = PreferenceManager.getDefaultSharedPreferences(itemView.getContext()); + mPrefs = PreferenceManager.getDefaultSharedPreferences(context); } @Override - public void bind(OpenHABWidget widget) { - OpenHABItem item = widget.item(); + public void bind(Widget widget) { + Item item = widget.item(); if (item != null) { float scalingFactor = mPrefs.getFloat(Constants.PREFERENCE_CHART_SCALING, 1.0f); float actualDensity = (float) mDensity / scalingFactor; StringBuilder chartUrl = new StringBuilder("chart?") - .append(item.type() == OpenHABItem.Type.Group ? "groups=" : "items=") + .append(item.type() == Item.Type.Group ? "groups=" : "items=") .append(item.name()) .append("&period=").append(widget.period()) .append("&random=").append(mRandom.nextInt()) @@ -929,14 +933,14 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { // FIXME: check for URL changes here if (!mVideoView.isPlaying()) { final String videoUrl; - OpenHABItem videoItem = widget.item(); + Item videoItem = widget.item(); if ("hls".equalsIgnoreCase(widget.encoding()) && videoItem != null - && videoItem.type() == OpenHABItem.Type.StringItem + && videoItem.type() == Item.Type.StringItem && videoItem.state() != null) { videoUrl = videoItem.state(); } else { @@ -973,7 +977,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap @SuppressLint("SetJavaScriptEnabled") @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { mWebView.loadUrl("about:blank"); ViewGroup.LayoutParams lp = mWebView.getLayoutParams(); int desiredHeightPixels = widget.height() > 0 @@ -995,7 +999,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public static class ColorViewHolder extends LabeledItemBaseViewHolder implements View.OnTouchListener, Handler.Callback, ColorPicker.OnColorChangedListener { - private OpenHABItem mBoundItem; + private Item mBoundItem; private final LayoutInflater mInflater; private final Handler mHandler = new Handler(this); @@ -1015,7 +1019,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { super.bind(widget); mBoundItem = widget.item(); } @@ -1024,7 +1028,8 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap public boolean onTouch(View v, MotionEvent motionEvent) { if (motionEvent.getActionMasked() == MotionEvent.ACTION_UP) { if (v.getTag() instanceof String) { - Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, (String) v.getTag()); + final String cmd = (String) v.getTag(); + Util.sendItemCommand(mConnection.getAsyncHttpClient(), mBoundItem, cmd); } else { showColorPickerDialog(); } @@ -1060,7 +1065,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap colorPicker.setOnColorChangedListener(this); colorPicker.setShowOldCenterColor(false); - float[] initialColor = mBoundItem.stateAsHSV(); + float[] initialColor = mBoundItem.stateAsHsv(); if (initialColor != null) { colorPicker.setColor(Color.HSVToColor(initialColor)); } @@ -1083,7 +1088,7 @@ public class OpenHABWidgetAdapter extends RecyclerView.Adapter<OpenHABWidgetAdap } @Override - public void bind(OpenHABWidget widget) { + public void bind(Widget widget) { mStreamer = new MjpegStreamer(mImageView, mConnection, widget.url()); } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetListFragment.java b/mobile/src/main/java/org/openhab/habdroid/ui/WidgetListFragment.java similarity index 57% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetListFragment.java rename to mobile/src/main/java/org/openhab/habdroid/ui/WidgetListFragment.java index a2e51ed4562c27fd1db3cd524e58af41fd2d2802..f45ab43cc549c704319563f27afb745a99ef4555 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWidgetListFragment.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/WidgetListFragment.java @@ -10,11 +10,8 @@ package org.openhab.habdroid.ui; import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.VisibleForTesting; import android.support.v4.app.Fragment; @@ -27,10 +24,10 @@ import android.view.View; import android.view.ViewGroup; import org.openhab.habdroid.R; -import org.openhab.habdroid.model.OpenHABItem; -import org.openhab.habdroid.model.OpenHABLabeledValue; -import org.openhab.habdroid.model.OpenHABLinkedPage; -import org.openhab.habdroid.model.OpenHABWidget; +import org.openhab.habdroid.model.Item; +import org.openhab.habdroid.model.LabeledValue; +import org.openhab.habdroid.model.LinkedPage; +import org.openhab.habdroid.model.Widget; import org.openhab.habdroid.util.CacheManager; import org.openhab.habdroid.util.Util; @@ -43,22 +40,21 @@ import java.util.Locale; * widgets from sitemap page with further navigation through sitemap and everything else! */ -public class OpenHABWidgetListFragment extends Fragment - implements OpenHABWidgetAdapter.ItemClickListener { - private static final String TAG = OpenHABWidgetListFragment.class.getSimpleName(); - // List adapter for list view of openHAB widgets - private OpenHABWidgetAdapter openHABWidgetAdapter; +public class WidgetListFragment extends Fragment + implements WidgetAdapter.ItemClickListener { + private static final String TAG = WidgetListFragment.class.getSimpleName(); + @VisibleForTesting public RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; + private WidgetAdapter mAdapter; // Url of current sitemap page displayed - private String displayPageUrl; + private String mPageUrl; // parent activity - private OpenHABMainActivity mActivity; - // Am I visible? + private MainActivity mActivity; private boolean mIsVisible = false; private String mTitle; - private SwipeRefreshLayout refreshLayout; + private SwipeRefreshLayout mRefreshLayout; private String mHighlightedPageLink; @Override @@ -75,7 +71,7 @@ public class OpenHABWidgetListFragment extends Fragment mTitle = args.getString("title"); } } - displayPageUrl = args.getString("displayPageUrl"); + mPageUrl = args.getString("displayPageUrl"); } @Override @@ -83,40 +79,35 @@ public class OpenHABWidgetListFragment extends Fragment super.onActivityCreated(savedInstanceState); Log.d(TAG, "onActivityCreated()"); Log.d(TAG, "isAdded = " + isAdded()); - mActivity = (OpenHABMainActivity) getActivity(); - - // We're using atmosphere so create an own client to not block the others - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(mActivity); + mActivity = (MainActivity) getActivity(); - openHABWidgetAdapter = new OpenHABWidgetAdapter(getActivity(), - mActivity.getConnection(), this); + mAdapter = new WidgetAdapter(mActivity, mActivity.getConnection(), this); mLayoutManager = new LinearLayoutManager(mActivity); mLayoutManager.setRecycleChildrenOnDetach(true); mRecyclerView.setRecycledViewPool(mActivity.getViewPool()); - mRecyclerView.addItemDecoration(new OpenHABWidgetAdapter.WidgetItemDecoration(mActivity)); + mRecyclerView.addItemDecoration(new WidgetAdapter.WidgetItemDecoration(mActivity)); mRecyclerView.setLayoutManager(mLayoutManager); - mRecyclerView.setAdapter(openHABWidgetAdapter); + mRecyclerView.setAdapter(mAdapter); } @Override - public void onSaveInstanceState(Bundle outState) { + public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putString("title", mTitle); } @Override - public void onItemClicked(OpenHABWidget openHABWidget) { - OpenHABLinkedPage linkedPage = openHABWidget.linkedPage(); + public void onItemClicked(Widget widget) { + LinkedPage linkedPage = widget.linkedPage(); if (mActivity != null && linkedPage != null) { - mActivity.onWidgetSelected(linkedPage, OpenHABWidgetListFragment.this); + mActivity.onWidgetSelected(linkedPage, WidgetListFragment.this); } } @Override - public void onItemLongClicked(final OpenHABWidget widget) { + public void onItemLongClicked(final Widget widget) { Log.d(TAG, "Widget type = " + widget.type()); ArrayList<String> labels = new ArrayList<>(); @@ -126,21 +117,21 @@ public class OpenHABWidgetListFragment extends Fragment // If the widget has mappings, we will populate names and commands with // values from those mappings if (widget.hasMappingsOrItemOptions()) { - for (OpenHABLabeledValue mapping : widget.getMappingsOrItemOptions()) { + for (LabeledValue mapping : widget.getMappingsOrItemOptions()) { labels.add(mapping.label()); commands.add(mapping.value()); } // Else we only can do it for Switch widget with On/Off/Toggle commands - } else if (widget.type() == OpenHABWidget.Type.Switch) { - OpenHABItem item = widget.item(); - if (item.isOfTypeOrGroupType(OpenHABItem.Type.Switch)) { + } else if (widget.type() == Widget.Type.Switch) { + Item item = widget.item(); + if (item.isOfTypeOrGroupType(Item.Type.Switch)) { labels.add(getString(R.string.nfc_action_on)); commands.add("ON"); labels.add(getString(R.string.nfc_action_off)); commands.add("OFF"); labels.add(getString(R.string.nfc_action_toggle)); commands.add("TOGGLE"); - } else if (item.isOfTypeOrGroupType(OpenHABItem.Type.Rollershutter)) { + } else if (item.isOfTypeOrGroupType(Item.Type.Rollershutter)) { labels.add(getString(R.string.nfc_action_up)); commands.add("UP"); labels.add(getString(R.string.nfc_action_down)); @@ -148,7 +139,7 @@ public class OpenHABWidgetListFragment extends Fragment labels.add(getString(R.string.nfc_action_toggle)); commands.add("TOGGLE"); } - } else if (widget.type() == OpenHABWidget.Type.Colorpicker) { + } else if (widget.type() == Widget.Type.Colorpicker) { labels.add(getString(R.string.nfc_action_on)); commands.add("ON"); labels.add(getString(R.string.nfc_action_off)); @@ -161,35 +152,27 @@ public class OpenHABWidgetListFragment extends Fragment } labels.add(getString(R.string.nfc_action_to_sitemap_page)); - final String[] labelArray = labels.toArray(new String[labels.size()]); + final String[] labelArray = labels.toArray(new String[0]); new AlertDialog.Builder(getActivity()) .setTitle(R.string.nfc_dialog_title) - .setItems(labelArray, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent writeTagIntent = new Intent(getActivity(), OpenHABWriteTagActivity.class); - writeTagIntent.putExtra("sitemapPage", displayPageUrl); - - if (which < labelArray.length - 1) { - writeTagIntent.putExtra("item", widget.item().name()); - writeTagIntent.putExtra("itemType", widget.item().type()); - writeTagIntent.putExtra("command", commands.get(which)); - } - startActivityForResult(writeTagIntent, 0); - Util.overridePendingTransition(getActivity(), false); + .setItems(labelArray, (dialog, which) -> { + Intent writeTagIntent = new Intent(getActivity(), WriteTagActivity.class); + writeTagIntent.putExtra("sitemapPage", mPageUrl); + + if (which < labelArray.length - 1) { + writeTagIntent.putExtra("item", widget.item().name()); + writeTagIntent.putExtra("itemType", widget.item().type()); + writeTagIntent.putExtra("command", commands.get(which)); } + startActivityForResult(writeTagIntent, 0); + Util.overridePendingTransition(getActivity(), false); }) .show(); } - @NonNull - private String getIconFormat() { - return PreferenceManager.getDefaultSharedPreferences(mActivity).getString("iconFormatType","PNG"); - } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment Log.i(TAG, "onCreateView"); Log.d(TAG, "isAdded = " + isAdded()); @@ -202,60 +185,45 @@ public class OpenHABWidgetListFragment extends Fragment Log.d(TAG, "isAdded = " + isAdded()); super.onViewCreated(view, savedInstanceState); mRecyclerView = view.findViewById(R.id.recyclerview); - refreshLayout = getView().findViewById(R.id.swiperefresh); - - Util.applySwipeLayoutColors(refreshLayout, R.attr.colorPrimary, R.attr.colorAccent); - refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - mActivity.showRefreshHintSnackbarIfNeeded(); - CacheManager.getInstance(getActivity()).clearCache(); - if (displayPageUrl != null) { - mActivity.triggerPageUpdate(displayPageUrl, true); - } + mRefreshLayout = getView().findViewById(R.id.swiperefresh); + + Util.applySwipeLayoutColors(mRefreshLayout, R.attr.colorPrimary, R.attr.colorAccent); + mRefreshLayout.setOnRefreshListener(() -> { + mActivity.showRefreshHintSnackbarIfNeeded(); + CacheManager.getInstance(getActivity()).clearCache(); + if (mPageUrl != null) { + mActivity.triggerPageUpdate(mPageUrl, true); } }); } - @Override - public void onDestroyView() { - Log.d(TAG, "onDestroyView"); - super.onDestroyView(); - } - @Override public void onStart() { Log.d(TAG, "onStart"); super.onStart(); - mActivity.triggerPageUpdate(displayPageUrl, false); - } - - @Override - public void onStop() { - Log.d(TAG, "onStop"); - super.onStop(); + mActivity.triggerPageUpdate(mPageUrl, false); } @Override - public void onPause () { + public void onPause() { super.onPause(); - Log.d(TAG, "onPause() " + displayPageUrl); + Log.d(TAG, "onPause() " + mPageUrl); Log.d(TAG, "isAdded = " + isAdded()); - if (openHABWidgetAdapter != null) { + if (mAdapter != null) { stopVisibleViewHolders(); } } @Override - public void setUserVisibleHint (boolean isVisibleToUser) { + public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); mIsVisible = isVisibleToUser; Log.d(TAG, String.format("isVisibleToUser(%B)", isVisibleToUser)); } - public static OpenHABWidgetListFragment withPage(String pageUrl, String pageTitle) { + public static WidgetListFragment withPage(String pageUrl, String pageTitle) { Log.d(TAG, "withPage(" + pageUrl + ")"); - OpenHABWidgetListFragment fragment = new OpenHABWidgetListFragment(); + WidgetListFragment fragment = new WidgetListFragment(); Bundle args = new Bundle(); args.putString("displayPageUrl", pageUrl); args.putString("title", pageTitle); @@ -265,14 +233,14 @@ public class OpenHABWidgetListFragment extends Fragment public void setHighlightedPageLink(String highlightedPageLink) { mHighlightedPageLink = highlightedPageLink; - if (openHABWidgetAdapter == null) { + if (mAdapter == null) { return; } if (highlightedPageLink != null) { - for (int i = 0; i < openHABWidgetAdapter.getItemCount(); i++) { - OpenHABLinkedPage page = openHABWidgetAdapter.getItem(i).linkedPage(); + for (int i = 0; i < mAdapter.getItemCount(); i++) { + LinkedPage page = mAdapter.getItem(i).linkedPage(); if (page != null && highlightedPageLink.equals(page.link())) { - if (openHABWidgetAdapter.setSelectedPosition(i)) { + if (mAdapter.setSelectedPosition(i)) { mLayoutManager.scrollToPosition(i); } return; @@ -280,25 +248,25 @@ public class OpenHABWidgetListFragment extends Fragment } } // We didn't find a matching page link, so unselect everything - openHABWidgetAdapter.setSelectedPosition(-1); + mAdapter.setSelectedPosition(-1); } - public void update(String pageTitle, List<OpenHABWidget> widgets) { + public void update(String pageTitle, List<Widget> widgets) { mTitle = pageTitle; - if (openHABWidgetAdapter != null) { - openHABWidgetAdapter.update(widgets, refreshLayout.isRefreshing()); + if (mAdapter != null) { + mAdapter.update(widgets, mRefreshLayout.isRefreshing()); setHighlightedPageLink(mHighlightedPageLink); - refreshLayout.setRefreshing(false); + mRefreshLayout.setRefreshing(false); } if (mActivity != null && mIsVisible) { mActivity.updateTitle(); } } - public void updateWidget(OpenHABWidget widget) { - if (openHABWidgetAdapter != null) { - openHABWidgetAdapter.updateWidget(widget); + public void updateWidget(Widget widget) { + if (mAdapter != null) { + mAdapter.updateWidget(widget); } } @@ -317,8 +285,8 @@ public class OpenHABWidgetListFragment extends Fragment final int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition(); final int lastVisibleItemPosition = mLayoutManager.findLastVisibleItemPosition(); for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; ++i) { - OpenHABWidgetAdapter.ViewHolder holder = - (OpenHABWidgetAdapter.ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i); + WidgetAdapter.ViewHolder holder = + (WidgetAdapter.ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i); if (holder != null) { holder.stop(); } @@ -328,6 +296,6 @@ public class OpenHABWidgetListFragment extends Fragment @Override public String toString() { return String.format(Locale.US, "%s [url=%s, title=%s]", - super.toString(), displayPageUrl, mTitle); + super.toString(), mPageUrl, mTitle); } } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWriteTagActivity.java b/mobile/src/main/java/org/openhab/habdroid/ui/WriteTagActivity.java similarity index 84% rename from mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWriteTagActivity.java rename to mobile/src/main/java/org/openhab/habdroid/ui/WriteTagActivity.java index 7ecd676c2364689329397ea891040f98a6c1bd88..21a403dd292d20384e0a75cfad270d17ce85d8ca 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/OpenHABWriteTagActivity.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/WriteTagActivity.java @@ -26,6 +26,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; @@ -47,8 +48,8 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -public class OpenHABWriteTagActivity extends AppCompatActivity { - private static final String TAG = OpenHABWriteTagActivity.class.getSimpleName(); +public class WriteTagActivity extends AppCompatActivity { + private static final String TAG = WriteTagActivity.class.getSimpleName(); private NfcAdapter mNfcAdapter; private String mSitemapPage; @@ -87,11 +88,11 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { private Fragment getFragment() { if (mNfcAdapter == null) { - return new NFCUnsupportedFragment(); + return new NfcUnsupportedFragment(); } else if (!mNfcAdapter.isEnabled()) { - return new NFCDisabledFragment(); + return new NfcDisabledFragment(); } else { - return new NFCWriteTagFragment(); + return new NfcWriteTagFragment(); } } @@ -138,19 +139,18 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { } Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); - //do something with tagFromIntent Log.d(TAG, "NFC TAG = " + tagFromIntent.toString()); Log.d(TAG, "Writing page " + mSitemapPage + " to tag"); TextView writeTagMessage = findViewById(R.id.write_tag_message); try { - URI sitemapURI = new URI(mSitemapPage); - if (!sitemapURI.getPath().startsWith("/rest/sitemaps")) { + URI sitemapUri = new URI(mSitemapPage); + if (!sitemapUri.getPath().startsWith("/rest/sitemaps")) { throw new URISyntaxException(mSitemapPage, "Expected a sitemap URL"); } StringBuilder uriToWrite = new StringBuilder("openhab://sitemaps"); - uriToWrite.append(sitemapURI.getPath().substring(14)); + uriToWrite.append(sitemapUri.getPath().substring(14)); if (!TextUtils.isEmpty(mItem) && !TextUtils.isEmpty(mCommand)) { uriToWrite.append("?item=").append(mItem).append("&command=").append(mCommand); } @@ -215,21 +215,21 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { } private void autoCloseActivity() { - new Handler().postDelayed(() -> finish(), 2000); + new Handler().postDelayed(this::finish, 2000); } - public static abstract class AbstractNFCFragment extends Fragment { + public abstract static class AbstractNfcFragment extends Fragment { @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_writenfc, container, false); final ImageView watermark = view.findViewById(R.id.nfc_watermark); - Drawable ic_nfc = getResources().getDrawable(R.drawable.ic_nfc_black_180dp); - ic_nfc.setColorFilter( + Drawable nfcIcon = getResources().getDrawable(R.drawable.ic_nfc_black_180dp); + nfcIcon.setColorFilter( ContextCompat.getColor(getActivity(), R.color.empty_list_text_color), PorterDuff.Mode.SRC_IN); - watermark.setImageDrawable(ic_nfc); + watermark.setImageDrawable(nfcIcon); return view; } @@ -239,10 +239,10 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { } } - public static class NFCUnsupportedFragment extends AbstractNFCFragment { + public static class NfcUnsupportedFragment extends AbstractNfcFragment { @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); getMessageTextView(view).setText(R.string.info_write_tag_unsupported); @@ -250,10 +250,10 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { } } - public static class NFCDisabledFragment extends AbstractNFCFragment { + public static class NfcDisabledFragment extends AbstractNfcFragment { @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); getMessageTextView(view).setText(R.string.info_write_tag_disabled); @@ -272,10 +272,10 @@ public class OpenHABWriteTagActivity extends AppCompatActivity { } } - public static class NFCWriteTagFragment extends AbstractNFCFragment { + public static class NfcWriteTagFragment extends AbstractNfcFragment { @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); view.findViewById(R.id.nfc_wait_progress).setVisibility(View.VISIBLE); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentController.java b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentController.java index d32db36625e71cd8638cc4bb41aac03ddc286820..bd3c9dbce0cb8b4697fea9e1a3ecda7d7e1d2a8c 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentController.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentController.java @@ -18,6 +18,7 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.AnimRes; import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.v4.app.Fragment; @@ -39,14 +40,14 @@ import android.widget.TextView; import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.core.connection.ConnectionFactory; -import org.openhab.habdroid.model.OpenHABLinkedPage; -import org.openhab.habdroid.model.OpenHABSitemap; -import org.openhab.habdroid.model.OpenHABWidget; +import org.openhab.habdroid.model.LinkedPage; import org.openhab.habdroid.model.ServerProperties; -import org.openhab.habdroid.ui.OpenHABMainActivity; -import org.openhab.habdroid.ui.OpenHABNotificationFragment; -import org.openhab.habdroid.ui.OpenHABPreferencesActivity; -import org.openhab.habdroid.ui.OpenHABWidgetListFragment; +import org.openhab.habdroid.model.Sitemap; +import org.openhab.habdroid.model.Widget; +import org.openhab.habdroid.ui.CloudNotificationListFragment; +import org.openhab.habdroid.ui.MainActivity; +import org.openhab.habdroid.ui.PreferencesActivity; +import org.openhab.habdroid.ui.WidgetListFragment; import java.util.ArrayList; import java.util.HashSet; @@ -56,7 +57,7 @@ import java.util.Set; import java.util.Stack; /** - * Controller class for the content area of {@link OpenHABMainActivity} + * Controller class for the content area of {@link MainActivity} * * It manages the stack of widget lists shown, and shows error UI if needed. * The layout of the content area is up to the respective subclasses. @@ -64,7 +65,7 @@ import java.util.Stack; public abstract class ContentController implements PageConnectionHolderFragment.ParentCallback { private static final String TAG = ContentController.class.getSimpleName(); - private final OpenHABMainActivity mActivity; + private final MainActivity mActivity; protected final FragmentManager mFm; protected Fragment mNoConnectionFragment; @@ -72,12 +73,12 @@ public abstract class ContentController implements PageConnectionHolderFragment. private PageConnectionHolderFragment mConnectionFragment; private Fragment mTemporaryPage; - protected OpenHABSitemap mCurrentSitemap; - protected OpenHABWidgetListFragment mSitemapFragment; - protected final Stack<Pair<OpenHABLinkedPage, OpenHABWidgetListFragment>> mPageStack = new Stack<>(); + protected Sitemap mCurrentSitemap; + protected WidgetListFragment mSitemapFragment; + protected final Stack<Pair<LinkedPage, WidgetListFragment>> mPageStack = new Stack<>(); private Set<String> mPendingDataLoadUrls = new HashSet<>(); - protected ContentController(OpenHABMainActivity activity) { + protected ContentController(MainActivity activity) { mActivity = activity; mFm = activity.getSupportFragmentManager(); @@ -97,8 +98,8 @@ public abstract class ContentController implements PageConnectionHolderFragment. * @param state Bundle to save state into */ public void onSaveInstanceState(Bundle state) { - ArrayList<OpenHABLinkedPage> pages = new ArrayList<>(); - for (Pair<OpenHABLinkedPage, OpenHABWidgetListFragment> item : mPageStack) { + ArrayList<LinkedPage> pages = new ArrayList<>(); + for (Pair<LinkedPage, WidgetListFragment> item : mPageStack) { pages.add(item.first); if (item.second.isAdded()) { mFm.putFragment(state, "pageFragment-" + item.first.link(), item.second); @@ -129,7 +130,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. public void onRestoreInstanceState(Bundle state) { mCurrentSitemap = state.getParcelable("controllerSitemap"); if (mCurrentSitemap != null) { - mSitemapFragment = (OpenHABWidgetListFragment) + mSitemapFragment = (WidgetListFragment) mFm.getFragment(state, "sitemapFragment"); if (mSitemapFragment == null) { mSitemapFragment = makeSitemapFragment(mCurrentSitemap); @@ -140,10 +141,10 @@ public abstract class ContentController implements PageConnectionHolderFragment. mDefaultProgressFragment = progressFragment; } - ArrayList<OpenHABLinkedPage> oldStack = state.getParcelableArrayList("controllerPages"); + ArrayList<LinkedPage> oldStack = state.getParcelableArrayList("controllerPages"); mPageStack.clear(); - for (OpenHABLinkedPage page : oldStack) { - OpenHABWidgetListFragment f = (OpenHABWidgetListFragment) + for (LinkedPage page : oldStack) { + WidgetListFragment f = (WidgetListFragment) mFm.getFragment(state, "pageFragment-" + page.link()); mPageStack.add(Pair.create(page, f != null ? f : makePageFragment(page))); } @@ -157,7 +158,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. * * @param sitemap Sitemap to show */ - public void openSitemap(OpenHABSitemap sitemap) { + public void openSitemap(Sitemap sitemap) { Log.d(TAG, "Opening sitemap " + sitemap); mCurrentSitemap = sitemap; // First clear the old fragment stack to show the progress spinner... @@ -176,9 +177,9 @@ public abstract class ContentController implements PageConnectionHolderFragment. * @param page Page link to follow * @param source Fragment this action was triggered from */ - public void openPage(OpenHABLinkedPage page, OpenHABWidgetListFragment source) { + public void openPage(LinkedPage page, WidgetListFragment source) { Log.d(TAG, "Opening page " + page); - OpenHABWidgetListFragment f = makePageFragment(page); + WidgetListFragment f = makePageFragment(page); while (!mPageStack.isEmpty() && mPageStack.peek().second != source) { mPageStack.pop(); } @@ -214,7 +215,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. mActivity.updateTitle(); } else { // we didn't find it - showTemporaryPage(OpenHABWidgetListFragment.withPage(url, null)); + showTemporaryPage(WidgetListFragment.withPage(url, null)); } } @@ -239,7 +240,8 @@ public abstract class ContentController implements PageConnectionHolderFragment. public void indicateMissingConfiguration(boolean resolveAttempted) { Log.d(TAG, "Indicate missing configuration (resolveAttempted " + resolveAttempted + ")"); resetState(); - mNoConnectionFragment = MissingConfigurationFragment.newInstance(mActivity, resolveAttempted); + mNoConnectionFragment = + MissingConfigurationFragment.newInstance(mActivity, resolveAttempted); updateFragmentState(FragmentUpdateReason.PAGE_UPDATE); mActivity.updateTitle(); } @@ -294,7 +296,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. * @param highlightedId ID of notification to be highlighted initially */ public final void openNotifications(@Nullable String highlightedId) { - showTemporaryPage(OpenHABNotificationFragment.newInstance(highlightedId)); + showTemporaryPage(CloudNotificationListFragment.newInstance(highlightedId)); } /** @@ -340,14 +342,14 @@ public abstract class ContentController implements PageConnectionHolderFragment. if (mNoConnectionFragment != null) { return null; } else if (mTemporaryPage != null) { - if (mTemporaryPage instanceof OpenHABNotificationFragment) { + if (mTemporaryPage instanceof CloudNotificationListFragment) { return mActivity.getString(R.string.app_notifications); - } else if (mTemporaryPage instanceof OpenHABWidgetListFragment) { - return ((OpenHABWidgetListFragment) mTemporaryPage).getTitle(); + } else if (mTemporaryPage instanceof WidgetListFragment) { + return ((WidgetListFragment) mTemporaryPage).getTitle(); } return null; } else { - OpenHABWidgetListFragment f = getFragmentForTitle(); + WidgetListFragment f = getFragmentForTitle(); return f != null ? f.getTitle() : null; } } @@ -404,9 +406,9 @@ public abstract class ContentController implements PageConnectionHolderFragment. } @Override - public void onPageUpdated(String pageUrl, String pageTitle, List<OpenHABWidget> widgets) { + public void onPageUpdated(String pageUrl, String pageTitle, List<Widget> widgets) { Log.d(TAG, "Got update for URL " + pageUrl + ", pending " + mPendingDataLoadUrls); - for (OpenHABWidgetListFragment f : collectWidgetFragments()) { + for (WidgetListFragment f : collectWidgetFragments()) { if (pageUrl.equals(f.getDisplayPageUrl())) { f.update(pageTitle, widgets); break; @@ -421,8 +423,8 @@ public abstract class ContentController implements PageConnectionHolderFragment. } @Override - public void onWidgetUpdated(String pageUrl, OpenHABWidget widget) { - for (OpenHABWidgetListFragment f : collectWidgetFragments()) { + public void onWidgetUpdated(String pageUrl, Widget widget) { + for (WidgetListFragment f : collectWidgetFragments()) { if (pageUrl.equals(f.getDisplayPageUrl())) { f.updateWidget(widget); break; @@ -431,7 +433,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. } protected abstract void executeStateUpdate(FragmentUpdateReason reason, boolean allowStateLoss); - protected abstract OpenHABWidgetListFragment getFragmentForTitle(); + protected abstract WidgetListFragment getFragmentForTitle(); protected void updateFragmentState(FragmentUpdateReason reason) { // Allow state loss if activity is still started, as we'll get @@ -439,7 +441,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. executeStateUpdate(reason, mActivity.isStarted()); } - private void handleNewWidgetFragment(OpenHABWidgetListFragment f) { + private void handleNewWidgetFragment(WidgetListFragment f) { mPendingDataLoadUrls.add(f.getDisplayPageUrl()); // no fragment update yet; fragment state will be updated when data arrives updateConnectionState(); @@ -464,7 +466,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. protected void updateConnectionState() { List<String> pageUrls = new ArrayList<>(); - for (OpenHABWidgetListFragment f : collectWidgetFragments()) { + for (WidgetListFragment f : collectWidgetFragments()) { pageUrls.add(f.getDisplayPageUrl()); } Iterator<String> pendingIter = mPendingDataLoadUrls.iterator(); @@ -483,26 +485,26 @@ public abstract class ContentController implements PageConnectionHolderFragment. updateConnectionState(); } - private List<OpenHABWidgetListFragment> collectWidgetFragments() { - List<OpenHABWidgetListFragment> result = new ArrayList<>(); + private List<WidgetListFragment> collectWidgetFragments() { + List<WidgetListFragment> result = new ArrayList<>(); if (mSitemapFragment != null) { result.add(mSitemapFragment); } - for (Pair<OpenHABLinkedPage, OpenHABWidgetListFragment> item : mPageStack) { + for (Pair<LinkedPage, WidgetListFragment> item : mPageStack) { result.add(item.second); } - if (mTemporaryPage instanceof OpenHABWidgetListFragment) { - result.add((OpenHABWidgetListFragment) mTemporaryPage); + if (mTemporaryPage instanceof WidgetListFragment) { + result.add((WidgetListFragment) mTemporaryPage); } return result; } - private OpenHABWidgetListFragment makeSitemapFragment(OpenHABSitemap sitemap) { - return OpenHABWidgetListFragment.withPage(sitemap.homepageLink(), sitemap.label()); + private WidgetListFragment makeSitemapFragment(Sitemap sitemap) { + return WidgetListFragment.withPage(sitemap.homepageLink(), sitemap.label()); } - private OpenHABWidgetListFragment makePageFragment(OpenHABLinkedPage page) { - return OpenHABWidgetListFragment.withPage(page.link(), page.title()); + private WidgetListFragment makePageFragment(LinkedPage page) { + return WidgetListFragment.withPage(page.link(), page.title()); } protected enum FragmentUpdateReason { @@ -548,7 +550,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. @Override public void onClick(View view) { - ((OpenHABMainActivity) getActivity()).retryServerPropertyQuery(); + ((MainActivity) getActivity()).retryServerPropertyQuery(); } } @@ -584,9 +586,10 @@ public abstract class ContentController implements PageConnectionHolderFragment. public static class MissingConfigurationFragment extends StatusFragment { public static MissingConfigurationFragment newInstance(Context context, - boolean resolveAttempted) { + boolean resolveAttempted) { MissingConfigurationFragment f = new MissingConfigurationFragment(); - @StringRes int textResId = resolveAttempted ? R.string.configuration_missing : R.string.no_remote_server; + @StringRes int textResId = + resolveAttempted ? R.string.configuration_missing : R.string.no_remote_server; f.setArguments(buildArgs(context.getString(textResId), R.drawable.ic_openhab_appicon_24dp, /* FIXME? */ R.string.go_to_settings_button, false)); @@ -595,7 +598,7 @@ public abstract class ContentController implements PageConnectionHolderFragment. @Override public void onClick(View view) { - Intent preferencesIntent = new Intent(getActivity(), OpenHABPreferencesActivity.class); + Intent preferencesIntent = new Intent(getActivity(), PreferencesActivity.class); TaskStackBuilder.create(getActivity()) .addNextIntentWithParentStack(preferencesIntent) .startActivities(); @@ -614,8 +617,8 @@ public abstract class ContentController implements PageConnectionHolderFragment. } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { Bundle arguments = getArguments(); View view = inflater.inflate(R.layout.fragment_status, container, false); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerOnePane.java b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerOnePane.java index a6558feca7d23cf3b6b16e1f08c5bd81b84fa65d..1121c0ab49882bd0ea9e088c44a310d668a03360 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerOnePane.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerOnePane.java @@ -14,12 +14,12 @@ import android.support.v4.app.FragmentTransaction; import android.view.ViewStub; import org.openhab.habdroid.R; -import org.openhab.habdroid.ui.OpenHABMainActivity; -import org.openhab.habdroid.ui.OpenHABWidgetListFragment; +import org.openhab.habdroid.ui.MainActivity; +import org.openhab.habdroid.ui.WidgetListFragment; @SuppressWarnings("unused") // instantiated via reflection public class ContentControllerOnePane extends ContentController { - public ContentControllerOnePane(OpenHABMainActivity activity) { + public ContentControllerOnePane(MainActivity activity) { super(activity); } @@ -45,7 +45,7 @@ public class ContentControllerOnePane extends ContentController { } @Override - protected OpenHABWidgetListFragment getFragmentForTitle() { + protected WidgetListFragment getFragmentForTitle() { return mPageStack.empty() ? mSitemapFragment : mPageStack.peek().second; } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerTwoPane.java b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerTwoPane.java index 9aa5d35646090e68dd303873b3104c8b5b04f2c8..233fabc82db359e4e22ace35af42ea4d383d2b51 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerTwoPane.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/activity/ContentControllerTwoPane.java @@ -17,15 +17,15 @@ import android.view.View; import android.view.ViewStub; import org.openhab.habdroid.R; -import org.openhab.habdroid.model.OpenHABLinkedPage; -import org.openhab.habdroid.ui.OpenHABMainActivity; -import org.openhab.habdroid.ui.OpenHABWidgetListFragment; +import org.openhab.habdroid.model.LinkedPage; +import org.openhab.habdroid.ui.MainActivity; +import org.openhab.habdroid.ui.WidgetListFragment; @SuppressWarnings("unused") // instantiated via reflection public class ContentControllerTwoPane extends ContentController { private View mRightContentView; - public ContentControllerTwoPane(OpenHABMainActivity activity) { + public ContentControllerTwoPane(MainActivity activity) { super(activity); } @@ -39,8 +39,8 @@ public class ContentControllerTwoPane extends ContentController { @Override protected void executeStateUpdate(FragmentUpdateReason reason, boolean allowStateLoss) { Fragment leftFragment = getOverridingFragment(); - final OpenHABWidgetListFragment rightFragment; - final Pair<OpenHABLinkedPage, OpenHABWidgetListFragment> rightPair; + final WidgetListFragment rightFragment; + final Pair<LinkedPage, WidgetListFragment> rightPair; if (leftFragment != null) { rightFragment = null; @@ -82,8 +82,8 @@ public class ContentControllerTwoPane extends ContentController { if (leftFragment != null) { ft.setCustomAnimations(determineEnterAnim(reason), determineExitAnim(reason)); ft.replace(R.id.content_left, leftFragment); - if (leftFragment instanceof OpenHABWidgetListFragment) { - OpenHABWidgetListFragment llf = (OpenHABWidgetListFragment) leftFragment; + if (leftFragment instanceof WidgetListFragment) { + WidgetListFragment llf = (WidgetListFragment) leftFragment; llf.setHighlightedPageLink(rightPair != null ? rightPair.first.link() : null); } } @@ -102,7 +102,7 @@ public class ContentControllerTwoPane extends ContentController { } @Override - public void openPage(OpenHABLinkedPage page, OpenHABWidgetListFragment source) { + public void openPage(LinkedPage page, WidgetListFragment source) { Fragment currentLeftFragment = mFm.findFragmentById(R.id.content_left); if (source == currentLeftFragment && !mPageStack.empty()) { mPageStack.pop(); @@ -111,7 +111,7 @@ public class ContentControllerTwoPane extends ContentController { } @Override - protected OpenHABWidgetListFragment getFragmentForTitle() { + protected WidgetListFragment getFragmentForTitle() { return mPageStack.size() > 1 ? mPageStack.get(mPageStack.size() - 2).second : mSitemapFragment; diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/activity/PageConnectionHolderFragment.java b/mobile/src/main/java/org/openhab/habdroid/ui/activity/PageConnectionHolderFragment.java index f6577ec5b6a635bc1747b0aa833958eff3824e50..b7b4a1976bba55c708513ee8b4e87cafc3475427 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/activity/PageConnectionHolderFragment.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/activity/PageConnectionHolderFragment.java @@ -11,11 +11,18 @@ import android.util.Log; import com.here.oksse.ServerSentEvent; +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.Response; + import org.json.JSONException; import org.json.JSONObject; import org.openhab.habdroid.core.connection.Connection; -import org.openhab.habdroid.model.OpenHABWidget; -import org.openhab.habdroid.model.OpenHABWidgetDataSource; +import org.openhab.habdroid.model.Widget; +import org.openhab.habdroid.model.WidgetDataSource; +import org.openhab.habdroid.ui.WidgetListFragment; import org.openhab.habdroid.util.AsyncHttpClient; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -34,15 +41,9 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.HttpUrl; -import okhttp3.Request; -import okhttp3.Response; - /** * Fragment that manages connections for active instances of - * {@link org.openhab.habdroid.ui.OpenHABWidgetListFragment} + * {@link WidgetListFragment} * * It retains the connections over activity recreations, and takes care of stopping * and restarting connections if needed. @@ -79,7 +80,7 @@ public class PageConnectionHolderFragment extends Fragment { * @param pageTitle Updated page title * @param widgets Updated list of widgets for the given page */ - void onPageUpdated(String pageUrl, String pageTitle, List<OpenHABWidget> widgets); + void onPageUpdated(String pageUrl, String pageTitle, List<Widget> widgets); /** * Let parent know about an update to the contents of a single widget. @@ -87,7 +88,7 @@ public class PageConnectionHolderFragment extends Fragment { * @param pageUrl URL of the page the updated widget belongs to * @param widget Updated widget */ - void onWidgetUpdated(String pageUrl, OpenHABWidget widget); + void onWidgetUpdated(String pageUrl, Widget widget); } private Map<String, ConnectionHandler> mConnections = new HashMap<>(); @@ -210,7 +211,7 @@ public class PageConnectionHolderFragment extends Fragment { private boolean mLongPolling; private String mAtmosphereTrackingId; private String mLastPageTitle; - private List<OpenHABWidget> mLastWidgetList; + private List<Widget> mLastWidgetList; private EventHelper mEventHelper; public ConnectionHandler(String pageUrl, Connection connection, ParentCallback cb) { @@ -264,7 +265,7 @@ public class PageConnectionHolderFragment extends Fragment { } Log.d(TAG, "Loading data for " + mUrl); - Map<String, String> headers = new HashMap<String, String>(); + Map<String, String> headers = new HashMap<>(); if (!mCallback.serverReturnsJson()) { headers.put("Accept", "application/xml"); } @@ -313,8 +314,8 @@ public class PageConnectionHolderFragment extends Fragment { return; } - OpenHABWidgetDataSource dataSource = - new OpenHABWidgetDataSource(mCallback.getIconFormat()); + WidgetDataSource dataSource = + new WidgetDataSource(mCallback.getIconFormat()); final boolean hasUpdate; if (mCallback.serverReturnsJson()) { hasUpdate = parseResponseJson(dataSource, response); @@ -323,10 +324,10 @@ public class PageConnectionHolderFragment extends Fragment { } if (hasUpdate) { - List<OpenHABWidget> widgetList = new ArrayList<>(); - for (OpenHABWidget w : dataSource.getWidgets()) { + List<Widget> widgetList = new ArrayList<>(); + for (Widget w : dataSource.getWidgets()) { // Remove frame widgets with no label text - if (w.type() == OpenHABWidget.Type.Frame && TextUtils.isEmpty(w.label())) { + if (w.type() == Widget.Type.Frame && TextUtils.isEmpty(w.label())) { continue; } widgetList.add(w); @@ -341,7 +342,7 @@ public class PageConnectionHolderFragment extends Fragment { load(); } - private boolean parseResponseXml(OpenHABWidgetDataSource dataSource, String response) { + private boolean parseResponseXml(WidgetDataSource dataSource, String response) { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = dbf.newDocumentBuilder(); @@ -362,7 +363,7 @@ public class PageConnectionHolderFragment extends Fragment { } } - private boolean parseResponseJson(OpenHABWidgetDataSource dataSource, String response) { + private boolean parseResponseJson(WidgetDataSource dataSource, String response) { try { JSONObject pageJson = new JSONObject(response); // In case of a server timeout in the long polling request, nothing is done @@ -389,9 +390,9 @@ public class PageConnectionHolderFragment extends Fragment { JSONObject object = new JSONObject(payload); String widgetId = object.getString("widgetId"); for (int i = 0; i < mLastWidgetList.size(); i++) { - OpenHABWidget widget = mLastWidgetList.get(i); + Widget widget = mLastWidgetList.get(i); if (widgetId.equals(widget.id())) { - OpenHABWidget updatedWidget = OpenHABWidget.updateFromEvent(widget, + Widget updatedWidget = Widget.updateFromEvent(widget, object, mCallback.getIconFormat()); mLastWidgetList.set(i, updatedWidget); mCallback.onWidgetUpdated(mUrl, updatedWidget); @@ -415,6 +416,7 @@ public class PageConnectionHolderFragment extends Fragment { interface FailureCallback { void handleFailure(); } + interface UpdateCallback { void handleUpdateEvent(String message); } @@ -515,7 +517,8 @@ public class PageConnectionHolderFragment extends Fragment { } @Override - public boolean onRetryError(ServerSentEvent sse, Throwable throwable, Response response) { + public boolean onRetryError(ServerSentEvent sse, + Throwable throwable, Response response) { // Stop retrying after maximum amount of subsequent retries is reached return ++mRetries < MAX_RETRIES; } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/ChartScalingPreference.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/ChartScalingPreference.java index 6fddce01585d245f759c8a55c2d14f10e8ba812d..f12933ffbbbf182804ddeca62b28df9b3a03cd3c 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/ChartScalingPreference.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/ChartScalingPreference.java @@ -31,7 +31,8 @@ public class ChartScalingPreference extends Preference implements SeekBar.OnSeek } @TargetApi(21) - public ChartScalingPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + public ChartScalingPreference(Context context, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/DividerItemDecoration.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/DividerItemDecoration.java index c6b72286e01d0ac701d79574771b1e38d33ec634..99c4a8624fee5e419a09baf7b08a85af5bdeb32e 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/DividerItemDecoration.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/DividerItemDecoration.java @@ -21,7 +21,7 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, View view, - RecyclerView parent, RecyclerView.State state) { + RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (mDivider != null && !suppressDividerForChild(view, parent)) { outRect.bottom = mDivider.getIntrinsicHeight(); diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/SegmentedControlButton.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/SegmentedControlButton.java index 18bac128830cc34f9cf490fe62da621284f257a6..95142c6c9c7460885bb07ebd25c08a9399ab346f 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/SegmentedControlButton.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/SegmentedControlButton.java @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2010-2016, openHAB.org and others. * * All rights reserved. This program and the accompanying materials @@ -23,12 +23,13 @@ import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; import android.support.v7.content.res.AppCompatResources; +import android.support.v7.widget.AppCompatRadioButton; import android.util.AttributeSet; import org.openhab.habdroid.R; /** @author benjamin ferrari */ -public class SegmentedControlButton extends android.support.v7.widget.AppCompatRadioButton { +public class SegmentedControlButton extends AppCompatRadioButton { private int mLineHeight; private float mX; @@ -42,23 +43,22 @@ public class SegmentedControlButton extends android.support.v7.widget.AppCompatR private Paint mBackgroundPaint; public SegmentedControlButton(Context context, AttributeSet attrs) { - super(context, attrs); - init(attrs); + this(context, attrs, 0); } public SegmentedControlButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(attrs); - } - - private void init(AttributeSet attrs) { setButtonDrawable(null); + if (attrs != null) { - TypedArray attributes = this.getContext().obtainStyledAttributes(attrs, R.styleable.SegmentedControlButton); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.SegmentedControlButton); - int lineColor = attributes.getColor(R.styleable.SegmentedControlButton_lineColor, 0); - mLineHeight = attributes.getDimensionPixelSize(R.styleable.SegmentedControlButton_lineHeight, 0); - mTextDistanceFromLine = attributes.getDimensionPixelSize(R.styleable.SegmentedControlButton_textDistanceFromLine, 0); + int lineColor = a.getColor(R.styleable.SegmentedControlButton_lineColor, 0); + mLineHeight = a.getDimensionPixelSize( + R.styleable.SegmentedControlButton_lineHeight, 0); + mTextDistanceFromLine = a.getDimensionPixelSize( + R.styleable.SegmentedControlButton_textDistanceFromLine, 0); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); @@ -69,13 +69,15 @@ public class SegmentedControlButton extends android.support.v7.widget.AppCompatR mLinePaint.setColor(lineColor); mLinePaint.setStyle(Style.FILL); - int bgColorResId = attributes.getResourceId(R.styleable.SegmentedControlButton_backgroundColor, 0); + int bgColorResId = a.getResourceId( + R.styleable.SegmentedControlButton_backgroundColor, 0); if (bgColorResId != 0) { - mBackgroundColorList = AppCompatResources.getColorStateList(getContext(), bgColorResId); + mBackgroundColorList = + AppCompatResources.getColorStateList(getContext(), bgColorResId); mBackgroundPaint = new Paint(); } - attributes.recycle(); + a.recycle(); } } @@ -83,7 +85,8 @@ public class SegmentedControlButton extends android.support.v7.widget.AppCompatR protected void drawableStateChanged() { super.drawableStateChanged(); if (mBackgroundColorList != null) { - mBackgroundPaint.setColor(mBackgroundColorList.getColorForState(getDrawableState(), 0)); + mBackgroundPaint.setColor( + mBackgroundColorList.getColorForState(getDrawableState(), 0)); } } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/SSLClientCertificatePreference.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/SslClientCertificatePreference.java similarity index 90% rename from mobile/src/main/java/org/openhab/habdroid/ui/widget/SSLClientCertificatePreference.java rename to mobile/src/main/java/org/openhab/habdroid/ui/widget/SslClientCertificatePreference.java index 6035ab4262368d15cc69c16b65e6b4a38d95144b..e815f24cb7c29a613377b78d32c3c4fc0260c22d 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/SSLClientCertificatePreference.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/SslClientCertificatePreference.java @@ -8,7 +8,6 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.preference.Preference; -import android.preference.PreferenceManager; import android.security.KeyChain; import android.security.KeyChainException; import android.security.keystore.KeyProperties; @@ -22,23 +21,24 @@ import org.openhab.habdroid.R; import java.security.cert.X509Certificate; -public class SSLClientCertificatePreference extends Preference { +public class SslClientCertificatePreference extends Preference { private Activity mActivity; private String mCurrentAlias; private ImageView mHelpIcon; - public SSLClientCertificatePreference(Context context, AttributeSet attrs) { + public SslClientCertificatePreference(Context context, AttributeSet attrs) { super(context, attrs); init(context); } - public SSLClientCertificatePreference(Context context, AttributeSet attrs, int defStyleAttr) { + public SslClientCertificatePreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } @TargetApi(21) - public SSLClientCertificatePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + public SslClientCertificatePreference(Context context, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } @@ -56,7 +56,8 @@ public class SSLClientCertificatePreference extends Preference { mHelpIcon = view.findViewById(R.id.help_icon); final Context context = getContext(); - Uri howToUri = Uri.parse(context.getString(R.string.settings_openhab_sslclientcert_howto_url)); + final Uri howToUri = Uri.parse( + context.getString(R.string.settings_openhab_sslclientcert_howto_url)); final Intent intent = new Intent(Intent.ACTION_VIEW, howToUri); if (intent.resolveActivity(context.getPackageManager()) != null) { diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/URLInputPreference.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/UrlInputPreference.java similarity index 86% rename from mobile/src/main/java/org/openhab/habdroid/ui/widget/URLInputPreference.java rename to mobile/src/main/java/org/openhab/habdroid/ui/widget/UrlInputPreference.java index e9cae365b747514d0e885286f1a7a71b2c5cea0e..38879342511d9f7260c42059088913a72aff8207 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/URLInputPreference.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/UrlInputPreference.java @@ -17,19 +17,19 @@ import org.openhab.habdroid.R; import java.net.MalformedURLException; import java.net.URL; -public class URLInputPreference extends EditTextPreference implements TextWatcher { +public class UrlInputPreference extends EditTextPreference implements TextWatcher { private EditText mEditor; private boolean mUrlIsValid; - public URLInputPreference(Context context) { + public UrlInputPreference(Context context) { super(context); } - public URLInputPreference(Context context, AttributeSet attrs) { + public UrlInputPreference(Context context, AttributeSet attrs) { super(context, attrs); } - public URLInputPreference(Context context, AttributeSet attrs, int defStyleAttr) { + public UrlInputPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -71,7 +71,8 @@ public class URLInputPreference extends EditTextPreference implements TextWatche } } } - mEditor.setError(mUrlIsValid ? null : mEditor.getResources().getString(R.string.error_invalid_url)); + mEditor.setError(mUrlIsValid + ? null : mEditor.getResources().getString(R.string.error_invalid_url)); updateOkButtonState(); } diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/widget/WidgetImageView.java b/mobile/src/main/java/org/openhab/habdroid/ui/widget/WidgetImageView.java index 7e9d8a2191c6ec42f80168da9918f29705261aea..f39498caf66a45a0e5689ffa52b0129375c92274 100644 --- a/mobile/src/main/java/org/openhab/habdroid/ui/widget/WidgetImageView.java +++ b/mobile/src/main/java/org/openhab/habdroid/ui/widget/WidgetImageView.java @@ -21,6 +21,11 @@ import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; import android.util.Log; +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.Request; + import org.openhab.habdroid.R; import org.openhab.habdroid.core.connection.Connection; import org.openhab.habdroid.util.AsyncHttpClient; @@ -29,11 +34,6 @@ import org.openhab.habdroid.util.HttpClient; import java.lang.ref.WeakReference; -import okhttp3.Call; -import okhttp3.Headers; -import okhttp3.HttpUrl; -import okhttp3.Request; - public class WidgetImageView extends AppCompatImageView { public static final String TAG = WidgetImageView.class.getSimpleName(); @@ -88,7 +88,8 @@ public class WidgetImageView extends AppCompatImageView { a.recycle(); } - mDefaultSvgSize = context.getResources().getDimensionPixelSize(R.dimen.svg_image_default_size); + mDefaultSvgSize = + context.getResources().getDimensionPixelSize(R.dimen.svg_image_default_size); mRefreshHandler = new RefreshHandler(this); } @@ -177,11 +178,9 @@ public class WidgetImageView extends AppCompatImageView { if (isEmpty && mEmptyHeightToWidthRatio > 0) { int specWidth = MeasureSpec.getSize(widthMeasureSpec); - switch (MeasureSpec.getMode(widthMeasureSpec)) { - case MeasureSpec.AT_MOST: - case MeasureSpec.EXACTLY: - setMeasuredDimension(specWidth, (int) (mEmptyHeightToWidthRatio * specWidth)); - break; + int specMode = MeasureSpec.getMode(widthMeasureSpec); + if (specMode == MeasureSpec.AT_MOST || specMode == MeasureSpec.EXACTLY) { + setMeasuredDimension(specWidth, (int) (mEmptyHeightToWidthRatio * specWidth)); } } } diff --git a/mobile/src/main/java/org/openhab/habdroid/util/AsyncHttpClient.java b/mobile/src/main/java/org/openhab/habdroid/util/AsyncHttpClient.java index d1471863e4fe1351776568007069f233c8f5452a..e6a665685c878679cd08b24de4bcc3b5f4c313aa 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/AsyncHttpClient.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/AsyncHttpClient.java @@ -17,14 +17,11 @@ import android.graphics.PorterDuff; import android.graphics.RectF; import android.os.Handler; import android.os.Looper; +import android.support.annotation.NonNull; import com.caverock.androidsvg.SVG; import com.caverock.androidsvg.SVGParseException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - import okhttp3.Call; import okhttp3.Callback; import okhttp3.Headers; @@ -34,21 +31,26 @@ import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + public class AsyncHttpClient extends HttpClient { public interface ResponseHandler<T> { - T convertBodyInBackground(ResponseBody body) throws IOException; // called in background thread + // called in background thread + T convertBodyInBackground(ResponseBody body) throws IOException; void onFailure(Request request, int statusCode, Throwable error); void onSuccess(T body, Headers headers); } - public static abstract class StringResponseHandler implements ResponseHandler<String> { + public abstract static class StringResponseHandler implements ResponseHandler<String> { @Override public String convertBodyInBackground(ResponseBody body) throws IOException { return body.string(); } } - public static abstract class BitmapResponseHandler implements ResponseHandler<Bitmap> { + public abstract static class BitmapResponseHandler implements ResponseHandler<Bitmap> { private final int mDefaultSize; public BitmapResponseHandler(int defaultSizePx) { @@ -58,11 +60,11 @@ public class AsyncHttpClient extends HttpClient { @Override public Bitmap convertBodyInBackground(ResponseBody body) throws IOException { MediaType contentType = body.contentType(); - boolean isSVG = contentType != null + boolean isSvg = contentType != null && contentType.type().equals("image") && contentType.subtype().contains("svg"); InputStream is = body.byteStream(); - if (isSVG) { + if (isSvg) { try { return getBitmapFromSvgInputstream(is); } catch (SVGParseException e) { @@ -108,7 +110,8 @@ public class AsyncHttpClient extends HttpClient { CachingMode.AVOID_CACHE, responseHandler); } - public <T> Call get(String url, Map<String, String> headers, ResponseHandler<T> responseHandler) { + public <T> Call get(String url, Map<String, String> headers, + ResponseHandler<T> responseHandler) { return method(url, "GET", headers, null, null, DEFAULT_TIMEOUT_MS, CachingMode.AVOID_CACHE, responseHandler); } @@ -124,7 +127,8 @@ public class AsyncHttpClient extends HttpClient { return method(url, "GET", null, null, null, timeoutMillis, caching, responseHandler); } - public Call post(String url, String requestBody, String mediaType, StringResponseHandler responseHandler) { + public Call post(String url, String requestBody, String mediaType, + StringResponseHandler responseHandler) { return method(url, "POST", null, requestBody, mediaType, DEFAULT_TIMEOUT_MS, CachingMode.AVOID_CACHE, responseHandler); } @@ -132,10 +136,11 @@ public class AsyncHttpClient extends HttpClient { private <T> Call method(String url, String method, Map<String, String> headers, String requestBody, String mediaType, long timeoutMillis, CachingMode caching, final ResponseHandler<T> responseHandler) { - Call call = prepareCall(url, method, headers, requestBody, mediaType, timeoutMillis, caching); + Call call = prepareCall(url, method, headers, + requestBody, mediaType, timeoutMillis, caching); call.enqueue(new Callback() { @Override - public void onFailure(final Call call, final IOException e) { + public void onFailure(@NonNull final Call call, final IOException e) { mHandler.post(() -> { if (!call.isCanceled()) { responseHandler.onFailure(call.request(), 0, e); diff --git a/mobile/src/main/java/org/openhab/habdroid/util/AsyncServiceResolver.java b/mobile/src/main/java/org/openhab/habdroid/util/AsyncServiceResolver.java index 81c1fe43ac326a0e43a5739fe626aef6d6243fe9..686df53cacc6d2fca593c2bf331755c444d0576e 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/AsyncServiceResolver.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/AsyncServiceResolver.java @@ -29,7 +29,7 @@ import javax.jmdns.ServiceInfo; import javax.jmdns.ServiceListener; public class AsyncServiceResolver extends Thread implements ServiceListener { - private final static String TAG = AsyncServiceResolver.class.getSimpleName(); + private static final String TAG = AsyncServiceResolver.class.getSimpleName(); public interface Listener { void onServiceResolved(ServiceInfo serviceInfo); @@ -45,7 +45,7 @@ public class AsyncServiceResolver extends Thread implements ServiceListener { private Listener mListener; private Handler mHandler; - private final static int DEFAULT_DISCOVERY_TIMEOUT = 3000; + private static final int DEFAULT_DISCOVERY_TIMEOUT = 3000; public AsyncServiceResolver(Context context, Listener listener, String serviceType) { super(); @@ -85,12 +85,14 @@ public class AsyncServiceResolver extends Thread implements ServiceListener { mHandler.post(() -> mListener.onServiceResolveFailed()); shutdown(); } - } catch (InterruptedException ignored) {} + } catch (InterruptedException ignored) { + // ignored + } } @Override public void serviceAdded(ServiceEvent event) { - Log.d(TAG, "Service added " + event.getName()); + Log.d(TAG, "Service added " + event.getName()); mJmdns.requestServiceInfo(event.getType(), event.getName(), 1); } @@ -120,14 +122,16 @@ public class AsyncServiceResolver extends Thread implements ServiceListener { private InetAddress getLocalIpv4Address() { try { - for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { + for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); + en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); - for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { + for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); + enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); Log.i(TAG, "IP: " + inetAddress.getHostAddress().toString()); Log.i(TAG, "Is IPV4 = " + (inetAddress instanceof Inet4Address)); if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) { - Log.i(TAG, "Selected " + inetAddress.getHostAddress().toString()); + Log.i(TAG, "Selected " + inetAddress.getHostAddress()); return inetAddress; } } diff --git a/mobile/src/main/java/org/openhab/habdroid/util/CacheManager.java b/mobile/src/main/java/org/openhab/habdroid/util/CacheManager.java index ec8641d96daabd4369b5037d4adb5bd0bbb39dfd..20e5678e3c00c31af06ca3bddbd78632e968b340 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/CacheManager.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/CacheManager.java @@ -13,12 +13,12 @@ import android.content.Context; import android.graphics.Bitmap; import android.util.LruCache; -import java.io.File; -import java.io.IOException; - import okhttp3.Cache; import okhttp3.HttpUrl; +import java.io.File; +import java.io.IOException; + public class CacheManager { private static CacheManager sInstance; private Cache mHttpCache; @@ -60,6 +60,7 @@ public class CacheManager { try { mHttpCache.evictAll(); } catch (IOException ignored) { + // ignored } } diff --git a/mobile/src/main/java/org/openhab/habdroid/util/HttpClient.java b/mobile/src/main/java/org/openhab/habdroid/util/HttpClient.java index 1075078dd60a0af8efd016454d4dd51eaa33f52b..afb62e3c7f95403fc597122bed1076c5569882d2 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/HttpClient.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/HttpClient.java @@ -13,9 +13,6 @@ import android.support.annotation.VisibleForTesting; import com.here.oksse.OkSse; -import java.util.Map; -import java.util.concurrent.TimeUnit; - import okhttp3.CacheControl; import okhttp3.Call; import okhttp3.Credentials; @@ -25,6 +22,9 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; +import java.util.Map; +import java.util.concurrent.TimeUnit; + public abstract class HttpClient { public enum CachingMode { DEFAULT, diff --git a/mobile/src/main/java/org/openhab/habdroid/util/SyncHttpClient.java b/mobile/src/main/java/org/openhab/habdroid/util/SyncHttpClient.java index 90e81894a06f403827728ea4b039c40056bb1bec..61834a39b9c10a208cc871068ba3f3b6dd203512 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/SyncHttpClient.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/SyncHttpClient.java @@ -9,18 +9,15 @@ package org.openhab.habdroid.util; -import android.content.Context; -import android.content.SharedPreferences; - -import java.io.IOException; -import java.util.Map; - import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; +import java.io.IOException; +import java.util.Map; + public class SyncHttpClient extends HttpClient { public static class HttpResult { public final Request request; @@ -53,6 +50,7 @@ public class SyncHttpClient extends HttpClient { public boolean isSuccessful() { return error == null; } + public void close() { if (response != null) { response.close(); @@ -62,6 +60,7 @@ public class SyncHttpClient extends HttpClient { public HttpTextResult asText() { return new HttpTextResult(this); } + public HttpStatusResult asStatus() { return new HttpStatusResult(this); } diff --git a/mobile/src/main/java/org/openhab/habdroid/util/Util.java b/mobile/src/main/java/org/openhab/habdroid/util/Util.java index e56f53271d3581398b36e5479a14afc0954e1b84..c9fd628d72a923fa059f0ba31b04b46b4f2636fb 100644 --- a/mobile/src/main/java/org/openhab/habdroid/util/Util.java +++ b/mobile/src/main/java/org/openhab/habdroid/util/Util.java @@ -11,11 +11,13 @@ package org.openhab.habdroid.util; import android.app.Activity; import android.app.ActivityManager; -import android.content.Context; +import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.Build; import android.preference.PreferenceManager; +import android.support.annotation.AnimRes; import android.support.annotation.AttrRes; import android.support.annotation.NonNull; import android.support.annotation.StyleRes; @@ -23,12 +25,15 @@ import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.util.TypedValue; +import okhttp3.Headers; +import okhttp3.Request; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.openhab.habdroid.R; -import org.openhab.habdroid.model.OpenHABItem; -import org.openhab.habdroid.model.OpenHABSitemap; +import org.openhab.habdroid.model.Item; +import org.openhab.habdroid.model.Sitemap; import org.w3c.dom.Document; import org.w3c.dom.NodeList; @@ -36,27 +41,18 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.List; -import okhttp3.Headers; -import okhttp3.Request; - -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; - public class Util { - - private final static String TAG = Util.class.getSimpleName(); + private static final String TAG = Util.class.getSimpleName(); public static void overridePendingTransition(Activity activity, boolean reverse) { - if (!PreferenceManager.getDefaultSharedPreferences(activity).getString(Constants.PREFERENCE_ANIMATION, "android").equals("android")) { - if (PreferenceManager.getDefaultSharedPreferences(activity).getString(Constants.PREFERENCE_ANIMATION, "android").equals("ios")) { - if (reverse) { - activity.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right); - } else { - activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left); - } + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); + if (!prefs.getString(Constants.PREFERENCE_ANIMATION, "android").equals("android")) { + if (prefs.getString(Constants.PREFERENCE_ANIMATION, "android").equals("ios")) { + @AnimRes int enterAnim = reverse ? R.anim.slide_in_left : R.anim.slide_in_right; + @AnimRes int exitAnim = reverse ? R.anim.slide_out_right : R.anim.slide_out_left; + activity.overridePendingTransition(enterAnim, exitAnim); } else { activity.overridePendingTransition(0, 0); } @@ -70,8 +66,9 @@ public class Util { normalizedUrl = url.toString(); normalizedUrl = normalizedUrl.replace("\n", ""); normalizedUrl = normalizedUrl.replace(" ", ""); - if (!normalizedUrl.endsWith("/")) + if (!normalizedUrl.endsWith("/")) { normalizedUrl = normalizedUrl + "/"; + } } catch (MalformedURLException e) { Log.e(TAG, "normalizeUrl: invalid URL"); } @@ -83,25 +80,25 @@ public class Util { return uri.getHost(); } - public static List<OpenHABSitemap> parseSitemapList(Document document) { - List<OpenHABSitemap> sitemapList = new ArrayList<OpenHABSitemap>(); + public static List<Sitemap> parseSitemapList(Document document) { + List<Sitemap> sitemapList = new ArrayList<>(); NodeList sitemapNodes = document.getElementsByTagName("sitemap"); if (sitemapNodes.getLength() > 0) { for (int i = 0; i < sitemapNodes.getLength(); i++) { - sitemapList.add(OpenHABSitemap.fromXml(sitemapNodes.item(i))); + sitemapList.add(Sitemap.fromXml(sitemapNodes.item(i))); } } return sitemapList; } - public static List<OpenHABSitemap> parseSitemapList(JSONArray jsonArray) { - List<OpenHABSitemap> sitemapList = new ArrayList<OpenHABSitemap>(); + public static List<Sitemap> parseSitemapList(JSONArray jsonArray) { + List<Sitemap> sitemapList = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { try { JSONObject sitemapJson = jsonArray.getJSONObject(i); - OpenHABSitemap openHABSitemap = OpenHABSitemap.fromJson(sitemapJson); - if (!(openHABSitemap.name().equals("_default") && jsonArray.length() != 1)) { - sitemapList.add(openHABSitemap); + Sitemap sitemap = Sitemap.fromJson(sitemapJson); + if (!(sitemap.name().equals("_default") && jsonArray.length() != 1)) { + sitemapList.add(sitemap); } } catch (JSONException e) { Log.d(TAG, "Error while parsing sitemap", e); @@ -110,34 +107,33 @@ public class Util { return sitemapList; } - public static void sortSitemapList(List<OpenHABSitemap> sitemapList, String defaultSitemapName) { + public static void sortSitemapList(List<Sitemap> sitemapList, String defaultSitemapName) { // Sort by sitename label, the default sitemap should be the first one - Collections.sort(sitemapList, new Comparator<OpenHABSitemap>() { - @Override - public int compare(OpenHABSitemap sitemap1, OpenHABSitemap sitemap2) { - if (sitemap1.name().equals(defaultSitemapName)) { - return -1; - } - if (sitemap2.name().equals(defaultSitemapName)) { - return 1; - } - return sitemap1.label().compareToIgnoreCase(sitemap2.label()); + Collections.sort(sitemapList, (lhs, rhs) -> { + if (lhs.name().equals(defaultSitemapName)) { + return -1; + } + if (rhs.name().equals(defaultSitemapName)) { + return 1; } + return lhs.label().compareToIgnoreCase(rhs.label()); }); } - public static boolean sitemapExists(List<OpenHABSitemap> sitemapList, String sitemapName) { + public static boolean sitemapExists(List<Sitemap> sitemapList, String sitemapName) { for (int i = 0; i < sitemapList.size(); i++) { - if (sitemapList.get(i).name().equals(sitemapName)) + if (sitemapList.get(i).name().equals(sitemapName)) { return true; + } } return false; } - public static OpenHABSitemap getSitemapByName(List<OpenHABSitemap> sitemapList, String sitemapName) { + public static Sitemap getSitemapByName(List<Sitemap> sitemapList, String sitemapName) { for (int i = 0; i < sitemapList.size(); i++) { - if (sitemapList.get(i).name().equals(sitemapName)) + if (sitemapList.get(i).name().equals(sitemapName)) { return sitemapList.get(i); + } } return null; } @@ -147,9 +143,9 @@ public class Util { } public static void setActivityTheme(@NonNull final Activity activity, String theme) { - activity.setTheme(getActivityThemeID(activity, theme)); + activity.setTheme(getActivityThemeId(activity, theme)); - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { TypedValue typedValue = new TypedValue(); activity.getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); activity.setTaskDescription(new ActivityManager.TaskDescription( @@ -159,11 +155,11 @@ public class Util { } } - public static @StyleRes int getActivityThemeID(@NonNull final Activity activity) { - return getActivityThemeID(activity, null); + public static @StyleRes int getActivityThemeId(@NonNull final Activity activity) { + return getActivityThemeId(activity, null); } - public static @StyleRes int getActivityThemeID(@NonNull final Activity activity, String theme) { + public static @StyleRes int getActivityThemeId(@NonNull final Activity activity, String theme) { if (theme == null) { theme = PreferenceManager.getDefaultSharedPreferences(activity).getString( Constants.PREFERENCE_THEME, activity.getString(R.string.theme_value_light)); @@ -195,7 +191,7 @@ public class Util { return false; } - public static void sendItemCommand(AsyncHttpClient client, OpenHABItem item, String command) { + public static void sendItemCommand(AsyncHttpClient client, Item item, String command) { if (item == null) { return; } @@ -206,7 +202,8 @@ public class Util { if (itemUrl == null || command == null) { return; } - client.post(itemUrl, command, "text/plain;charset=UTF-8", new AsyncHttpClient.StringResponseHandler() { + client.post(itemUrl, command, "text/plain;charset=UTF-8", + new AsyncHttpClient.StringResponseHandler() { @Override public void onFailure(Request request, int statusCode, Throwable error) { Log.e(TAG, "Got command error " + error.getMessage()); @@ -236,8 +233,8 @@ public class Util { */ public static String obfuscateString(String string, int clearTextCharCount) { clearTextCharCount = Math.min(string.length(), clearTextCharCount); - return string.substring(0, clearTextCharCount) + - string.substring(clearTextCharCount).replaceAll(".", "*"); + return string.substring(0, clearTextCharCount) + + string.substring(clearTextCharCount).replaceAll(".", "*"); } /** diff --git a/mobile/src/main/res/layout-v21/chart_scaling_pref.xml b/mobile/src/main/res/layout-v21/chart_scaling_pref.xml index 323782773cf32ccb238615c97827588bead20659..cf2ed497e2d63695682dd7e586f173fbbb795cc1 100644 --- a/mobile/src/main/res/layout-v21/chart_scaling_pref.xml +++ b/mobile/src/main/res/layout-v21/chart_scaling_pref.xml @@ -14,7 +14,7 @@ android:orientation="vertical"> <TextView - android:id="@+android:id/title" + android:id="@android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" diff --git a/mobile/src/main/res/layout/chart_scaling_pref.xml b/mobile/src/main/res/layout/chart_scaling_pref.xml index 688ce17e3ea02f511d02f72c2ac3cddc481d285f..f3dba4e7eb60ce0a2434081bca7e0a7d85026746 100644 --- a/mobile/src/main/res/layout/chart_scaling_pref.xml +++ b/mobile/src/main/res/layout/chart_scaling_pref.xml @@ -14,7 +14,7 @@ android:orientation="vertical"> <TextView - android:id="@+android:id/title" + android:id="@android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" diff --git a/mobile/src/main/res/layout/openhabwritetag.xml b/mobile/src/main/res/layout/openhabwritetag.xml index a48e7de868bd1de914eb38ffdb1fe3555239c356..23eef454fd2e02736ac96688b2be45bd96c1e6d7 100644 --- a/mobile/src/main/res/layout/openhabwritetag.xml +++ b/mobile/src/main/res/layout/openhabwritetag.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent" android:layout_gravity="center" android:orientation="vertical" - tools:context="org.openhab.habdroid.ui.OpenHABWriteTagActivity"> + tools:context="org.openhab.habdroid.ui.WriteTagActivity"> <android.support.v7.widget.Toolbar android:id="@+id/openhab_toolbar" diff --git a/mobile/src/main/res/xml/local_connection_preferences.xml b/mobile/src/main/res/xml/local_connection_preferences.xml index dcd4541e8e358016bcbc73d9fdb4191e8acb7cd3..b989e3c3d019284b8e44d4704b58b60f2e5ba04b 100644 --- a/mobile/src/main/res/xml/local_connection_preferences.xml +++ b/mobile/src/main/res/xml/local_connection_preferences.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/settings_openhab_connection"> - <org.openhab.habdroid.ui.widget.URLInputPreference + <org.openhab.habdroid.ui.widget.UrlInputPreference android:defaultValue="@string/empty_string" android:inputType="textNoSuggestions" android:key="default_openhab_url" diff --git a/mobile/src/main/res/xml/preferences.xml b/mobile/src/main/res/xml/preferences.xml index b6d1c96941cc9d64f43ab40ea13d1b662b570992..962af85bfcd2f9de955657fd2c48f976ab944f1e 100644 --- a/mobile/src/main/res/xml/preferences.xml +++ b/mobile/src/main/res/xml/preferences.xml @@ -20,7 +20,7 @@ android:title="@string/settings_openhab_alt_connection" android:dependency="default_openhab_demomode" android:icon="@drawable/ic_tree_grey_24dp" /> - <org.openhab.habdroid.ui.widget.SSLClientCertificatePreference + <org.openhab.habdroid.ui.widget.SslClientCertificatePreference android:defaultValue="@string/settings_openhab_none" android:key="default_openhab_sslclientcert" android:summary="@string/settings_openhab_none" diff --git a/mobile/src/main/res/xml/remote_connection_preferences.xml b/mobile/src/main/res/xml/remote_connection_preferences.xml index 5e31cba055da55fbb95e8baf9952cd0e77cba528..dea0bf538c5e2d848110bd2e06f100c903d37f01 100644 --- a/mobile/src/main/res/xml/remote_connection_preferences.xml +++ b/mobile/src/main/res/xml/remote_connection_preferences.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/settings_openhab_alt_connection"> - <org.openhab.habdroid.ui.widget.URLInputPreference + <org.openhab.habdroid.ui.widget.UrlInputPreference android:defaultValue="@string/empty_string" android:inputType="textNoSuggestions" android:key="default_openhab_alturl" diff --git a/mobile/src/test/java/org/openhab/habdroid/core/connection/ConnectionFactoryTest.java b/mobile/src/test/java/org/openhab/habdroid/core/connection/ConnectionFactoryTest.java index a2cf2ca54fc582e8415b3653d49bb5230dfd28bb..3a5f2c2efdbafb051b4cf10a5a035ad9e8cd317a 100644 --- a/mobile/src/test/java/org/openhab/habdroid/core/connection/ConnectionFactoryTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/core/connection/ConnectionFactoryTest.java @@ -10,13 +10,14 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.openhab.habdroid.core.connection.exception.ConnectionException; import org.openhab.habdroid.core.connection.exception.NetworkNotAvailableException; import org.openhab.habdroid.core.connection.exception.NetworkNotSupportedException; @@ -26,9 +27,6 @@ import org.openhab.habdroid.util.Constants; import java.io.File; import java.io.IOException; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; @@ -41,96 +39,96 @@ import static org.mockito.Mockito.when; public class ConnectionFactoryTest { @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); + public TemporaryFolder mTempFolder = new TemporaryFolder(); - private Context mockContext; - private ConnectivityManager mockConnectivityService; - private SharedPreferences mockSettings; + private Context mMockContext; + private ConnectivityManager mMockConnectivityService; + private SharedPreferences mMockPrefs; @Before public void setup() throws IOException { - mockConnectivityService = Mockito.mock(ConnectivityManager.class); + mMockConnectivityService = Mockito.mock(ConnectivityManager.class); - File cacheFolder = tempFolder.newFolder("cache"); - File appDir = tempFolder.newFolder(); + File cacheFolder = mTempFolder.newFolder("cache"); + File appDir = mTempFolder.newFolder(); - mockContext = Mockito.mock(Application.class); - Mockito.when(mockContext.getApplicationContext()).thenReturn(mockContext); - Mockito.when(mockContext.getCacheDir()).thenReturn(cacheFolder); - Mockito.when(mockContext.getDir(anyString(), anyInt())) + mMockContext = Mockito.mock(Application.class); + Mockito.when(mMockContext.getApplicationContext()).thenReturn(mMockContext); + Mockito.when(mMockContext.getCacheDir()).thenReturn(cacheFolder); + Mockito.when(mMockContext.getDir(anyString(), anyInt())) .then(invocation -> new File(appDir, invocation.getArgument(0).toString())); - when(mockContext.getString(anyInt())).thenReturn(""); - when(mockContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) - .thenReturn(mockConnectivityService); - when(mockContext.getMainLooper()).thenReturn(Looper.getMainLooper()); + when(mMockContext.getString(anyInt())).thenReturn(""); + when(mMockContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) + .thenReturn(mMockConnectivityService); + when(mMockContext.getMainLooper()).thenReturn(Looper.getMainLooper()); - mockSettings = Mockito.mock(SharedPreferences.class); + mMockPrefs = Mockito.mock(SharedPreferences.class); - ConnectionFactory.initialize(mockContext, mockSettings); + ConnectionFactory.initialize(mMockContext, mMockPrefs); ConnectionFactory.sInstance.mMainHandler = makeMockedHandler(); ConnectionFactory.sInstance.mUpdateHandler = makeMockedHandler(); } @Test - public void testGetConnectionRemoteWithUrl() throws ConnectionException, IOException { + public void testGetConnectionRemoteWithUrl() throws IOException { MockWebServer server = new MockWebServer(); server.enqueue(new MockResponse().setResponseCode(404)); server.start(); - when(mockSettings.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) + when(mMockPrefs.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) .thenReturn(server.url("/").toString()); ConnectionFactory.sInstance.updateConnections(); Connection conn = ConnectionFactory.getConnection(Connection.TYPE_REMOTE); - assertNotNull("Requesting a remote connection when a remote url is set, " + - " should return a connection.", conn); + assertNotNull("Requesting a remote connection when a remote url is set, " + + " should return a connection.", conn); assertEquals("The connection type of a remote connection should be TYPE_REMOTE.", Connection.TYPE_REMOTE, conn.getConnectionType()); } @Test - public void testGetConnectionRemoteWithoutUrl() throws ConnectionException { - when(mockSettings.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) + public void testGetConnectionRemoteWithoutUrl() { + when(mMockPrefs.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) .thenReturn(""); ConnectionFactory.sInstance.updateConnections(); Connection conn = ConnectionFactory.getConnection(Connection.TYPE_REMOTE); - assertNull("Requesting a remote connection when a remote url isn't set, should not " + - "return a connection.", conn); + assertNull("Requesting a remote connection when a remote url isn't set, " + + "should not return a connection.", conn); } @Test - public void testGetConnectionLocalWithUrl() throws ConnectionException { - when(mockSettings.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) + public void testGetConnectionLocalWithUrl() { + when(mMockPrefs.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) .thenReturn("https://openhab.local:8080"); ConnectionFactory.sInstance.updateConnections(); Connection conn = ConnectionFactory.getConnection(Connection.TYPE_LOCAL); - assertNotNull("Requesting a local connection when local url is set, should " + - "return a connection.", conn); + assertNotNull("Requesting a local connection when local url is set, " + + "should return a connection.", conn); assertEquals("The connection type of a local connection should be LOGLEVEL_LOCAL.", Connection.TYPE_LOCAL, conn.getConnectionType()); } @Test - public void testGetConnectionLocalWithoutUrl() throws ConnectionException { - when(mockSettings.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) + public void testGetConnectionLocalWithoutUrl() { + when(mMockPrefs.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) .thenReturn(""); ConnectionFactory.sInstance.updateConnections(); Connection conn = ConnectionFactory.getConnection(Connection.TYPE_LOCAL); - assertNull("Requesting a remote connection when a local url isn't set, should not " + - "return a connection.", conn); + assertNull("Requesting a remote connection when a local url isn't set, " + + "should not return a connection.", conn); } @Test - public void testGetConnectionCloudWithUrl() throws ConnectionException, IOException { + public void testGetConnectionCloudWithUrl() throws IOException { MockWebServer server = new MockWebServer(); server.enqueue(new MockResponse().setBody("{'gcm': { 'senderId': '12345'} }")); server.start(); - when(mockSettings.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) + when(mMockPrefs.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) .thenReturn(server.url("/").toString()); ConnectionFactory.sInstance.updateConnections(); @@ -167,7 +165,7 @@ public class ConnectionFactoryTest { server.enqueue(new MockResponse().setResponseCode(404)); server.start(); - when(mockSettings.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) + when(mMockPrefs.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) .thenReturn(server.url("/").toString()); ConnectionFactory.sInstance.updateConnections(); triggerNetworkUpdate(ConnectivityManager.TYPE_WIFI); @@ -188,9 +186,9 @@ public class ConnectionFactoryTest { server.enqueue(new MockResponse().setResponseCode(404)); server.start(); - when(mockSettings.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) + when(mMockPrefs.getString(eq(Constants.PREFERENCE_REMOTE_URL), anyString())) .thenReturn(server.url("/").toString()); - when(mockSettings.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) + when(mMockPrefs.getString(eq(Constants.PREFERENCE_LOCAL_URL), anyString())) .thenReturn("https://myopenhab.org:443"); ConnectionFactory.sInstance.updateConnections(); triggerNetworkUpdate(ConnectivityManager.TYPE_WIFI); @@ -207,7 +205,7 @@ public class ConnectionFactoryTest { @Test(expected = NoUrlInformationException.class) public void testGetAnyConnectionWifiNoLocalNoRemote() throws ConnectionException { - when(mockSettings.getString(anyString(), anyString())).thenReturn(null); + when(mMockPrefs.getString(anyString(), anyString())).thenReturn(null); triggerNetworkUpdate(ConnectivityManager.TYPE_WIFI); ConnectionFactory.getUsableConnection(); @@ -221,45 +219,32 @@ public class ConnectionFactoryTest { } private void triggerNetworkUpdate(NetworkInfo info) { - when(mockConnectivityService.getActiveNetworkInfo()).thenReturn(info); + when(mMockConnectivityService.getActiveNetworkInfo()).thenReturn(info); - ConnectionFactory.sInstance.onReceive(mockContext, + ConnectionFactory.sInstance.onReceive(mMockContext, new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); } private Handler makeMockedHandler() { final Handler h = Mockito.mock(Handler.class); - when(h.sendEmptyMessage(anyInt())).thenAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { - Message msg = new Message(); - msg.what = invocationOnMock.getArgument(0); - ConnectionFactory.sInstance.handleMessage(msg); - return Boolean.TRUE; - } - }); - when(h.sendMessage(any(Message.class))).thenAnswer(new Answer<Boolean>() { - @Override - public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { - Message msg = invocationOnMock.getArgument(0); - ConnectionFactory.sInstance.handleMessage(msg); - return Boolean.TRUE; - } - }); - when(h.obtainMessage(anyInt())).thenAnswer(new Answer<Message>() { - @Override - public Message answer(InvocationOnMock invocationOnMock) throws Throwable { - return makeMockedMessage(h, invocationOnMock.getArgument(0), null); - } + when(h.sendEmptyMessage(anyInt())).thenAnswer(invocation -> { + Message msg = new Message(); + msg.what = invocation.getArgument(0); + ConnectionFactory.sInstance.handleMessage(msg); + return Boolean.TRUE; }); - when(h.obtainMessage(anyInt(), any())).thenAnswer(new Answer<Message>() { - @Override - public Message answer(InvocationOnMock invocationOnMock) throws Throwable { - return makeMockedMessage(h, - invocationOnMock.getArgument(0), - invocationOnMock.getArgument(1)); - } + when(h.sendMessage(any(Message.class))).thenAnswer(invocation -> { + Message msg = invocation.getArgument(0); + ConnectionFactory.sInstance.handleMessage(msg); + return Boolean.TRUE; }); + when(h.obtainMessage(anyInt())) + .thenAnswer(invocation -> makeMockedMessage(h, invocation.getArgument(0), null)); + when(h.obtainMessage(anyInt(), any())) + .thenAnswer(invocation -> { + return makeMockedMessage(h, invocation.getArgument(0), + invocation.getArgument(1)); + }); return h; } diff --git a/mobile/src/test/java/org/openhab/habdroid/core/connection/DefaultConnectionTest.java b/mobile/src/test/java/org/openhab/habdroid/core/connection/DefaultConnectionTest.java index bbf789e5079b1cc0ba7e36682d651ef52f1fe0b0..b0c6464aabde0bacf4da55f876fe57fcf3f263cd 100644 --- a/mobile/src/test/java/org/openhab/habdroid/core/connection/DefaultConnectionTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/core/connection/DefaultConnectionTest.java @@ -1,83 +1,82 @@ package org.openhab.habdroid.core.connection; +import okhttp3.Credentials; +import okhttp3.OkHttpClient; + import org.junit.Before; import org.junit.Test; import org.openhab.habdroid.util.AsyncHttpClient; import org.openhab.habdroid.util.HttpClient; import org.openhab.habdroid.util.SyncHttpClient; -import okhttp3.Credentials; -import okhttp3.OkHttpClient; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; public class DefaultConnectionTest { private static final String TEST_BASE_URL = "https://demo.local:8443"; - private OkHttpClient client; + private OkHttpClient mClient; - private Connection testConnection; - private Connection testConnectionRemote; - private Connection testConnectionCloud; + private Connection mTestConnection; + private Connection mTestConnectionRemote; + private Connection mTestConnectionCloud; @Before public void setup() { - client = new OkHttpClient.Builder().build(); - testConnection = new DefaultConnection(client, Connection.TYPE_LOCAL, + mClient = new OkHttpClient.Builder().build(); + mTestConnection = new DefaultConnection(mClient, Connection.TYPE_LOCAL, TEST_BASE_URL, null, null); - testConnectionRemote = new DefaultConnection(client, Connection.TYPE_REMOTE, + mTestConnectionRemote = new DefaultConnection(mClient, Connection.TYPE_REMOTE, null, null, null); - testConnectionCloud = new DefaultConnection(client, + mTestConnectionCloud = new DefaultConnection(mClient, Connection.TYPE_CLOUD, null, null, null); } @Test public void testGetConnectionTypeSetRemote() { - assertEquals(Connection.TYPE_REMOTE, testConnectionRemote.getConnectionType()); + assertEquals(Connection.TYPE_REMOTE, mTestConnectionRemote.getConnectionType()); } @Test public void testGetConnectionTypeSetLocal() { - assertEquals(Connection.TYPE_LOCAL, testConnection.getConnectionType()); + assertEquals(Connection.TYPE_LOCAL, mTestConnection.getConnectionType()); } @Test public void testGetConnectionTypeSetCloud() { - assertEquals(Connection.TYPE_CLOUD, testConnectionCloud.getConnectionType()); + assertEquals(Connection.TYPE_CLOUD, mTestConnectionCloud.getConnectionType()); } @Test public void testGetUsernameNotSet() { - assertNull(testConnection.getUsername()); + assertNull(mTestConnection.getUsername()); } @Test public void testGetPasswordNotSet() { - assertNull(testConnection.getPassword()); + assertNull(mTestConnection.getPassword()); } @Test public void testGetUsernameSet() { - Connection connection = new DefaultConnection(client, Connection.TYPE_LOCAL, + Connection connection = new DefaultConnection(mClient, Connection.TYPE_LOCAL, TEST_BASE_URL, "Test-User", null); assertEquals("Test-User", connection.getUsername()); } @Test public void testGetPasswordSet() { - Connection connection = new DefaultConnection(client, Connection.TYPE_LOCAL, + Connection connection = new DefaultConnection(mClient, Connection.TYPE_LOCAL, TEST_BASE_URL, null, "Test-Password"); assertEquals("Test-Password", connection.getPassword()); } @Test public void testGetSyncHttpClientCached() { - SyncHttpClient client1 = testConnection.getSyncHttpClient(); - SyncHttpClient client2 = testConnection.getSyncHttpClient(); + SyncHttpClient client1 = mTestConnection.getSyncHttpClient(); + SyncHttpClient client2 = mTestConnection.getSyncHttpClient(); assertNotNull(client1); assertEquals(client1, client2); @@ -85,8 +84,8 @@ public class DefaultConnectionTest { @Test public void testGetAsyncHttpClientCached() { - AsyncHttpClient client1 = testConnection.getAsyncHttpClient(); - AsyncHttpClient client2 = testConnection.getAsyncHttpClient(); + AsyncHttpClient client1 = mTestConnection.getAsyncHttpClient(); + AsyncHttpClient client2 = mTestConnection.getAsyncHttpClient(); assertNotNull(client1); assertEquals(client1, client2); @@ -94,19 +93,19 @@ public class DefaultConnectionTest { @Test public void testAsyncHasNoUsernamePassword() { - HttpClient httpClient = testConnection.getAsyncHttpClient(); + HttpClient httpClient = mTestConnection.getAsyncHttpClient(); assertNull(httpClient.mAuthHeader); } @Test public void testSyncHasNoUsernamePassword() { - HttpClient httpClient = testConnection.getSyncHttpClient(); + HttpClient httpClient = mTestConnection.getSyncHttpClient(); assertNull(httpClient.mAuthHeader); } @Test public void testAsyncHasUsernamePassword() { - Connection connection = new DefaultConnection(client, Connection.TYPE_LOCAL, + Connection connection = new DefaultConnection(mClient, Connection.TYPE_LOCAL, TEST_BASE_URL, "Test-User", "Test-Password"); HttpClient httpClient = connection.getAsyncHttpClient(); @@ -116,7 +115,7 @@ public class DefaultConnectionTest { @Test public void testSyncHasUsernamePassword() { - Connection connection = new DefaultConnection(client, Connection.TYPE_LOCAL, + Connection connection = new DefaultConnection(mClient, Connection.TYPE_LOCAL, TEST_BASE_URL, "Test-User", "Test-Password"); HttpClient httpClient = connection.getSyncHttpClient(); @@ -126,12 +125,12 @@ public class DefaultConnectionTest { @Test public void testSyncResolveRelativeUrl() { - SyncHttpClient.HttpResult result = testConnection.getSyncHttpClient().get("rest/test"); + SyncHttpClient.HttpResult result = mTestConnection.getSyncHttpClient().get("rest/test"); assertFalse("The request should never succeed in tests", result.isSuccessful()); assertEquals(TEST_BASE_URL + "/rest/test", result.request.url().toString()); result.close(); - result = testConnection.getSyncHttpClient().get("/rest/test"); + result = mTestConnection.getSyncHttpClient().get("/rest/test"); assertEquals(TEST_BASE_URL + "/rest/test", result.request.url().toString()); result.close(); } @@ -139,7 +138,7 @@ public class DefaultConnectionTest { @Test public void testSyncResolveAbsoluteUrl() { SyncHttpClient.HttpResult result = - testConnection.getSyncHttpClient().get("http://mylocalmachine.local/rest/test"); + mTestConnection.getSyncHttpClient().get("http://mylocalmachine.local/rest/test"); assertFalse("The request should never succeed in tests", result.isSuccessful()); assertEquals("http://mylocalmachine.local/rest/test", result.request.url().toString()); result.close(); diff --git a/mobile/src/test/java/org/openhab/habdroid/core/connection/DemoConnectionTest.java b/mobile/src/test/java/org/openhab/habdroid/core/connection/DemoConnectionTest.java index 1541e12f0e9d18182f5479d0c590977d1920f1b9..f791ab8e518e0612f850c27c56856109534f1de0 100644 --- a/mobile/src/test/java/org/openhab/habdroid/core/connection/DemoConnectionTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/core/connection/DemoConnectionTest.java @@ -1,34 +1,34 @@ package org.openhab.habdroid.core.connection; +import okhttp3.OkHttpClient; + import org.junit.Before; import org.junit.Test; -import okhttp3.OkHttpClient; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; public class DemoConnectionTest { - private Connection testConnection; + private Connection mTestConnection; @Before public void setup() { OkHttpClient client = new OkHttpClient.Builder().build(); - testConnection = new DemoConnection(client); + mTestConnection = new DemoConnection(client); } @Test public void testGetConnectionType() { - assertEquals(Connection.TYPE_REMOTE, testConnection.getConnectionType()); + assertEquals(Connection.TYPE_REMOTE, mTestConnection.getConnectionType()); } @Test public void testGetUsername() { - assertNull(testConnection.getUsername()); + assertNull(mTestConnection.getUsername()); } @Test public void testGetPassword() { - assertNull(testConnection.getPassword()); + assertNull(mTestConnection.getPassword()); } } diff --git a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABItemTest.java b/mobile/src/test/java/org/openhab/habdroid/model/ItemTest.java similarity index 69% rename from mobile/src/test/java/org/openhab/habdroid/model/OpenHABItemTest.java rename to mobile/src/test/java/org/openhab/habdroid/model/ItemTest.java index 388ba5e4f05bf6a72655f22a3c926fc778ef377f..75d1d13a71755488bb428419124ec91660124fb7 100644 --- a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABItemTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/model/ItemTest.java @@ -6,55 +6,57 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; @RunWith(MockitoJUnitRunner.class) -public class OpenHABItemTest { +public class ItemTest { @Test public void getStateAsBoolean_stateOff_returnFalse() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("OFF")); + Item sut = Item.fromJson(itemJsonForState("OFF")); assertFalse(sut.stateAsBoolean()); } @Test public void getStateAsBoolean_stateON_returnTrue() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("ON")); + Item sut = Item.fromJson(itemJsonForState("ON")); assertTrue(sut.stateAsBoolean()); } @Test public void getStateAsBoolean_stateNull_returnFalse() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState(null)); + Item sut = Item.fromJson(itemJsonForState(null)); assertFalse(sut.stateAsBoolean()); } @Test public void getStateAsBoolean_stateNegativeInteger_returnFalse() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("-42")); + Item sut = Item.fromJson(itemJsonForState("-42")); assertFalse(sut.stateAsBoolean()); } @Test public void getStateAsBoolean_statePositiveInteger_returnTrue() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("42")); + Item sut = Item.fromJson(itemJsonForState("42")); assertTrue(sut.stateAsBoolean()); } @Test public void getStateAsBoolean_stateIsZero_returnFalse() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("0")); + Item sut = Item.fromJson(itemJsonForState("0")); assertFalse(sut.stateAsBoolean()); } @Test - public void getStateAsBoolean_stateHSBBrightnessZero_returnFalse() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("10,10,0")); + public void getStateAsBoolean_stateHsbBrightnessZero_returnFalse() throws Exception { + Item sut = Item.fromJson(itemJsonForState("10,10,0")); assertFalse(sut.stateAsBoolean()); } @Test - public void getStateAsBoolean_stateHSBBrightnessPositive_returnTrue() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(itemJsonForState("10,10,50")); + public void getStateAsBoolean_stateHsbBrightnessPositive_returnTrue() throws Exception { + Item sut = Item.fromJson(itemJsonForState("10,10,50")); assertTrue(sut.stateAsBoolean()); } @@ -68,18 +70,18 @@ public class OpenHABItemTest { JSONObject object = new JSONObject(); object.put("name", "TestItem"); object.put("type", "Dummy"); - assertFalse(OpenHABItem.fromJson(object).readOnly()); + assertFalse(Item.fromJson(object).readOnly()); object.put("stateDescription", new JSONObject().put("readOnly", true)); - assertTrue(OpenHABItem.fromJson(object).readOnly()); + assertTrue(Item.fromJson(object).readOnly()); object.put("stateDescription", new JSONObject().put("readOnly", false)); - assertFalse(OpenHABItem.fromJson(object).readOnly()); + assertFalse(Item.fromJson(object).readOnly()); } @Test public void getMembers() throws Exception { - OpenHABItem sut = OpenHABItem.fromJson(new JSONObject("{ 'members': [" + Item sut = Item.fromJson(new JSONObject("{ 'members': [" + "{ 'state': '52.5200066,13.4029540', 'type': 'Location'," + "'name': 'GroupDemoLocation', 'label': 'Location 1'," + "'groupNames': [ 'LocationGroup' ] }," @@ -89,7 +91,7 @@ public class OpenHABItemTest { + "], 'state': 'NULL', 'type': 'Group'," + "'name': 'LocationGroup', 'label': 'Location Group' }")); assertEquals(2, sut.members().size()); - assertEquals(OpenHABItem.Type.Location, sut.members().get(0).type()); + assertEquals(Item.Type.Location, sut.members().get(0).type()); assertEquals("Location 2", sut.members().get(1).label()); } } \ No newline at end of file diff --git a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABSitemapTest.java b/mobile/src/test/java/org/openhab/habdroid/model/OpenHABSitemapTest.java deleted file mode 100644 index fcdad129c819392acfde7deed5983be4d6ad71f3..0000000000000000000000000000000000000000 --- a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABSitemapTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.openhab.habdroid.model; - -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; - -import static org.junit.Assert.*; - -@RunWith(MockitoJUnitRunner.class) -public class OpenHABSitemapTest { - OpenHABSitemap demoSitemapWithLabel; - OpenHABSitemap homeSitemapWithoutLabel; - - @Before - public void initSitemaps() throws JSONException { - String jsonString = "{\"name\":\"demo\",\"label\":\"Main Menu\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo/demo\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}"; - JSONObject jsonObject = new JSONObject(jsonString); - demoSitemapWithLabel = OpenHABSitemap.fromJson(jsonObject); - - jsonString = "{\"name\":\"home\",\"icon\":\"home\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home/home\",\"leaf\":true,\"timeout\":false,\"widgets\":[]}}"; - jsonObject = new JSONObject(jsonString); - homeSitemapWithoutLabel = OpenHABSitemap.fromJson(jsonObject); - } - - @Test - public void sitemapLabelNonNull() { - assertEquals("Main Menu", demoSitemapWithLabel.label()); - assertEquals("Sitemap without explicit label should return name for getLabel","home", homeSitemapWithoutLabel.label()); - } - - @Test - public void testGetLink() { - assertEquals("http://demo.openhab.org:8080/rest/sitemaps/demo", demoSitemapWithLabel.link()); - assertEquals("http://demo.openhab.org:8080/rest/sitemaps/home", homeSitemapWithoutLabel.link()); - } - - @Test - public void testGetHomepageLink() { - assertEquals("http://demo.openhab.org:8080/rest/sitemaps/demo/demo", demoSitemapWithLabel.homepageLink()); - assertEquals("http://demo.openhab.org:8080/rest/sitemaps/home/home", homeSitemapWithoutLabel.homepageLink()); - } - - @Test - public void testGetIcon() { - assertNull(demoSitemapWithLabel.icon()); - assertEquals("home", homeSitemapWithoutLabel.icon()); - } - - @Test - public void testGetName() { - assertEquals("demo", demoSitemapWithLabel.name()); - assertEquals("home", homeSitemapWithoutLabel.name()); - } -} diff --git a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABWidgetTest.java b/mobile/src/test/java/org/openhab/habdroid/model/OpenHABWidgetTest.java deleted file mode 100644 index 5eaecbd5db38c60793ad73a4456f663b852bc911..0000000000000000000000000000000000000000 --- a/mobile/src/test/java/org/openhab/habdroid/model/OpenHABWidgetTest.java +++ /dev/null @@ -1,412 +0,0 @@ -package org.openhab.habdroid.model; - -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.xml.sax.InputSource; - -import java.io.StringReader; -import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; - -@RunWith(MockitoJUnitRunner.class) -public class OpenHABWidgetTest { - List<OpenHABWidget> sutXml = new ArrayList<>(); - List<OpenHABWidget> sut1 = new ArrayList<>(); - List<OpenHABWidget> sut2 = new ArrayList<>(); - List<OpenHABWidget> sut3 = new ArrayList<>(); - - @Test - @Before - public void parse_createsOpenHABWidget() throws Exception { - OpenHABWidget.parseXml(sutXml, null, createXmlNode()); - OpenHABWidget.parseJson(sut1, null, createJSONObject(1), "PNG"); - OpenHABWidget.parseJson(sut2, null, createJSONObject(2), "SVG"); - OpenHABWidget.parseJson(sut3, null, createJSONObject(3), "SVG"); - } - - @Test - public void testCountInstances() throws Exception { - assertEquals(sutXml.size(), 2); - assertEquals(sut1.size(), 2); - assertEquals(sut2.size(), 1); - assertEquals(sut3.size(), 4); - } - - @Test - public void getIconPath_iconExists_returnIconUrlfromImages() throws Exception { - assertEquals("images/groupicon.png", sutXml.get(0).iconPath()); - } - - @Test - public void testGetIconPath() throws Exception { - assertEquals("icon/groupicon?state=OFF&format=PNG", sut1.get(0).iconPath()); - assertEquals("icon/groupicon?state=ON&format=SVG", sut2.get(0).iconPath()); - assertEquals("icon/slider?state=81&format=SVG", sut3.get(1).iconPath()); - assertEquals("Rollersutter icon must always be 0 to 100, not ON/OFF", "icon/rollershutter?state=0&format=SVG", sut3.get(2).iconPath()); - assertEquals("icon/rollershutter?state=42&format=SVG", sut3.get(3).iconPath()); - } - - @Test - public void testGetChildren() throws Exception { - assertEquals("demo11", sut1.get(1).id()); - assertEquals("0202_0_0_1", sut3.get(2).id()); - } - - @Test - public void testGetPeriod() throws Exception { - assertEquals("M", sut1.get(0).period()); - assertEquals("Object has no period, should default to 'D'", "D", sut2.get(0).period()); - } - - @Test - public void testGetStep() throws Exception { - assertEquals(1F, sut1.get(0).step()); - // this is invalid in JSON (< 0), expected to be adjusted - assertEquals(0.1F, sut2.get(0).step()); - } - - @Test - public void testGetRefresh() throws Exception { - assertEquals(1000, sut1.get(0).refresh()); - assertEquals("Min refresh is 100, object has set refresh to 10", 100, sut2.get(0).refresh()); - assertEquals("Missing refresh should equal 0", 0, sut3.get(0).refresh()); - } - - @Test - public void testHasItem() throws Exception { - assertNotNull(sut1.get(0).item()); - assertNotNull(sut2.get(0).item()); - } - - @Test - public void testHasLinkedPage() throws Exception { - assertNotNull(sut1.get(0).linkedPage()); - assertNull(sut2.get(0).linkedPage()); - } - - @Test - public void testHasMappings() throws Exception { - assertEquals(true, sut1.get(0).hasMappings()); - assertEquals(true, sut2.get(0).hasMappings()); - } - - @Test - public void testGetColors() throws Exception { - assertEquals("white", sut1.get(0).iconColor()); - assertEquals("#ff0000", sut1.get(0).labelColor()); - assertEquals("#00ffff", sut1.get(0).valueColor()); - assertEquals("orange", sut2.get(0).iconColor()); - assertEquals("blue", sut2.get(0).labelColor()); - assertEquals("red", sut2.get(0).valueColor()); - } - - @Test - public void testGetType() throws Exception { - assertEquals(OpenHABWidget.Type.Group, sut1.get(0).type()); - assertEquals(OpenHABWidget.Type.Group, sut2.get(0).type()); - assertEquals(OpenHABWidget.Type.Frame, sut3.get(0).type()); - assertEquals(OpenHABWidget.Type.Switch, sut3.get(2).type()); - assertEquals(OpenHABWidget.Type.Group, sut3.get(3).type()); - } - - @Test - public void testGetLabel() throws Exception { - assertEquals("Group1", sut1.get(0).label()); - assertEquals("Group1", sut2.get(0).label()); - assertEquals("Dimmer [81 %]", sut3.get(1).label()); - } - - @Test - public void testGetMappings() throws Exception { - assertEquals("ON", sut1.get(0).mappings().get(0).value()); - assertEquals("On", sut1.get(0).mappings().get(0).label()); - assertEquals("abcäöüßẞèéóò\uD83D\uDE03", sut2.get(0).mappings().get(0).label()); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testGetMappingNoMapping() throws Exception { - sut3.get(1).mappings().get(0); - } - - @Test - public void testGetMinValue() throws Exception { - assertEquals(0.0F, sut1.get(0).minValue()); - assertEquals(99.7F, sut2.get(0).minValue()); - } - - @Test - public void testGetMaxValue() throws Exception { - assertEquals(10.0F, sut1.get(0).maxValue()); - // this is invalid in JSON (max < min), expected to be adjusted - assertEquals(99.7F, sut2.get(0).maxValue()); - } - - @Test - public void testGetUrl() throws Exception { - assertEquals("http://localhost/url", sut1.get(0).url()); - assertEquals("http://localhost/url", sut2.get(0).url()); - assertEquals(null, sut3.get(1).url()); - } - - @Test - public void testGetLegend() throws Exception { - assertEquals(new Boolean(true), sut1.get(0).legend()); - assertEquals(new Boolean(false), sut2.get(0).legend()); - assertEquals(null, sut3.get(1).legend()); - } - - @Test - public void testGetHeight() throws Exception { - assertEquals(10, sut1.get(0).height()); - assertEquals(42, sut2.get(0).height()); - } - - @Test - public void testGetService() throws Exception { - assertEquals("D", sut1.get(0).service()); - assertEquals("XYZ", sut2.get(0).service()); - } - - @Test - public void testGetId() throws Exception { - assertEquals("demo", sut1.get(0).id()); - assertEquals("demo", sut2.get(0).id()); - } - - @Test - public void testGetEncoding() throws Exception { - assertEquals("mpeg", sut1.get(0).encoding()); - assertEquals(null, sut2.get(0).encoding()); - } - - private Node createXmlNode() throws Exception { - String xml = "" + - "<widget>" + - " <widgetId>demo</widgetId>" + - " <type>Group</type>" + - " <label>Group1</label>" + - " <icon>groupicon</icon>" + - " <url>http://localhost/url</url>" + - " <minValue>0.0</minValue>" + - " <maxValue>10.0</maxValue>" + - " <step>1</step>" + - " <refresh>10</refresh>" + - " <period>D</period>" + - " <service>D</service>" + - " <height>10</height>" + - " <iconcolor>white</iconcolor>" + - " <labelcolor>white</labelcolor>" + - " <valuecolor>white</valuecolor>" + - " <encoding></encoding>" + - " <mapping>" + - " <command>ON</command>\n" + - " <label>On</label>" + - " </mapping>" + - " <item>" + - " <type>GroupItem</type>" + - " <name>group1</name>" + - " <state>Undefined</state>" + - " <link>http://localhost/rest/items/group1</link>" + - " </item>" + - " <linkedPage>" + - " <id>0001</id>" + - " <title>LinkedPage</title>" + - " <icon>linkedpageicon</icon>" + - " <link>http://localhost/rest/sitemaps/demo/0001</link>" + - " <leaf>false</leaf>" + - " </linkedPage>" + - " <widget>" + - " <widgetId>demo11</widgetId>" + - " <type>Switch</type>" + - " </widget>" + - "</widget>"; - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = dbf.newDocumentBuilder(); - Document document = builder.parse(new InputSource(new StringReader(xml))); - Node rootNode = document.getFirstChild(); - return rootNode; - } - - /** - * @param id get different json objects depending on the id - * 1: All values are set - * 2: Different colors, no periode, max step size < 1, chart refresh < 100 - * 3: Frame with Slider, Rollershutter switch and Rollershutter group - * - * @return JSON object - * @throws Exception when no object with id is found - */ - private JSONObject createJSONObject(int id) throws Exception { - String json; - switch(id) { - case 1: - json = "{\n" + - " \"widgetId\": \"demo\",\n" + - " \"type\": \"Group\",\n" + - " \"label\": \"Group1\",\n" + - " \"icon\": \"groupicon\",\n" + - " \"url\": \"http://localhost/url\",\n" + - " \"minValue\": \"0.0\",\n" + - " \"maxValue\": \"10.0\",\n" + - " \"step\": \"1\",\n" + - " \"refresh\": \"1000\",\n" + - " \"period\": \"M\",\n" + - " \"service\": \"D\",\n" + - " \"height\": \"10\",\n" + - " \"legend\": \"true\",\n" + - " \"iconcolor\": \"white\",\n" + - " \"labelcolor\": \"#ff0000\",\n" + - " \"valuecolor\": \"#00ffff\",\n" + - " \"encoding\": \"mpeg\",\n" + - " \"mappings\": [{\n" + - " \"command\": \"ON\",\n" + - " \"label\": \"On\"\n" + - " }],\n" + - " \"item\": {\n" + - " \"type\": \"GroupItem\",\n" + - " \"name\": \"group1\",\n" + - " \"state\": \"OFF\",\n" + - " \"link\": \"http://localhost/rest/items/group1\"\n" + - " },\n" + - " \"linkedPage\": {\n" + - " \"id\": \"0001\",\n" + - " \"title\": \"LinkedPage\",\n" + - " \"icon\": \"linkedpageicon\",\n" + - " \"link\": \"http://localhost/rest/sitemaps/demo/0001\",\n" + - " \"leaf\": \"false\"\n" + - " },\n" + - " \"widgets\": [{ \"widgetId\": \"demo11\", \"type\": \"Switch\" }]\n" + - " }"; - break; - case 2: - json = "{\n" + - " \"widgetId\": \"demo\",\n" + - " \"type\": \"Group\",\n" + - " \"label\": \"Group1\",\n" + - " \"icon\": \"groupicon\",\n" + - " \"url\": \"http://localhost/url\",\n" + - " \"minValue\": \"99.7\",\n" + - " \"maxValue\": \"-10.0\",\n" + - " \"step\": \"-0.1\",\n" + - " \"refresh\": \"10\",\n" + - " \"service\": \"XYZ\",\n" + - " \"legend\": \"false\",\n" + - " \"height\": \"42\",\n" + - " \"iconcolor\": \"orange\",\n" + - " \"labelcolor\": \"blue\",\n" + - " \"valuecolor\": \"red\",\n" + - " \"mappings\": [{\n" + - " \"command\": \"ON\",\n" + - " \"label\": \"abcäöüßẞèéóò\uD83D\uDE03\"\n" + - " }],\n" + - " \"item\": {\n" + - " \"type\": \"Switch\",\n" + - " \"name\": \"switch1\",\n" + - " \"state\": \"ON\",\n" + - " \"link\": \"http://localhost/rest/items/switch1\"\n" + - " },\n" + - " }"; - break; - case 3: - json = "{\"widgetId\": \"0202_0\"," + - "\"type\": \"Frame\"," + - "\"label\": \"Percent-based Widgets\"," + - "\"icon\": \"frame\"," + - "\"mappings\": []," + - "\"widgets\": [" + - "{" + - "\"widgetId\": \"0202_0_0\"," + - "\"type\": \"Slider\"," + - "\"label\": \"Dimmer [81 %]\"," + - "\"icon\": \"slider\"," + - "\"mappings\": []," + - "\"switchSupport\": true," + - "\"sendFrequency\": 0," + - "\"item\": {" + - "\"link\": \"http://openhab.local:8080/rest/items/DimmedLight\"," + - "\"state\": \"81\"," + - "\"stateDescription\": {" + - "\"pattern\": \"%d %%\"," + - "\"readOnly\": false," + - "\"options\": []" + - "}," + - "\"type\": \"Dimmer\"," + - "\"name\": \"DimmedLight\"," + - "\"label\": \"Dimmer\"," + - "\"category\": \"slider\"," + - "\"tags\": []," + - "\"groupNames\": []" + - "}," + - "\"widgets\": []" + - "}," + - "{" + - "\"widgetId\": \"0202_0_0_1\"," + - "\"type\": \"Switch\"," + - "\"label\": \"Roller Shutter\"," + - "\"icon\": \"rollershutter\"," + - "\"mappings\": []," + - "\"item\": {" + - "\"link\": \"http://openhab.local:8080/rest/items/DemoShutter\"," + - "\"state\": \"0\"," + - "\"type\": \"Rollershutter\"," + - "\"name\": \"DemoShutter\"," + - "\"label\": \"Roller Shutter\"," + - "\"tags\": []," + - "\"groupNames\": [" + - "\"Shutters\"" + - "]" + - "}," + - "\"widgets\": []" + - "}," + - "{" + - "\"widgetId\": \"0202_0_0_1_2\"," + - "\"type\": \"Group\"," + - "\"label\": \"Shutters\"," + - "\"icon\": \"rollershutter\"," + - "\"mappings\": []," + - "\"item\": {" + - "\"members\": []," + - "\"groupType\": \"Rollershutter\"," + - "\"function\": {" + - "\"name\": \"AVG\"" + - "}," + - "\"link\": \"http://openhab.local:8080/rest/items/Shutters\"," + - "\"state\": \"42\"," + - "\"type\": \"Group\"," + - "\"name\": \"Shutters\"," + - "\"category\": \"rollershutter\"," + - "\"tags\": []," + - "\"groupNames\": []" + - "}," + - "\"linkedPage\": {" + - "\"id\": \"02020002\"," + - "\"title\": \"Shutters\"," + - "\"icon\": \"rollershutter\"," + - "\"link\": \"http://openhab.local:8080/rest/sitemaps/demo/02020002\"," + - "\"leaf\": true," + - "\"timeout\": false" + - "}," + - "\"widgets\": []" + - "}" + - "]" + - "}"; - break; - default: - throw new InvalidParameterException(); - } - return new JSONObject(json); - } -} diff --git a/mobile/src/test/java/org/openhab/habdroid/model/SitemapTest.java b/mobile/src/test/java/org/openhab/habdroid/model/SitemapTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c137c85944089cc3cb4e748cee322981c382546a --- /dev/null +++ b/mobile/src/test/java/org/openhab/habdroid/model/SitemapTest.java @@ -0,0 +1,69 @@ +package org.openhab.habdroid.model; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(MockitoJUnitRunner.class) +public class SitemapTest { + private Sitemap mDemoSitemapWithLabel; + private Sitemap mHomeSitemapWithoutLabel; + + @Before + public void initSitemaps() throws JSONException { + String jsonString = "{\"name\":\"demo\",\"label\":\"Main Menu\"," + + "\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo\"," + + "\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo/demo\"," + + "\"leaf\":false,\"timeout\":false,\"widgets\":[]}}"; + JSONObject jsonObject = new JSONObject(jsonString); + mDemoSitemapWithLabel = Sitemap.fromJson(jsonObject); + + jsonString = "{\"name\":\"home\",\"icon\":\"home\"," + + "\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home\"," + + "\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home/home\"," + + "\"leaf\":true,\"timeout\":false,\"widgets\":[]}}"; + jsonObject = new JSONObject(jsonString); + mHomeSitemapWithoutLabel = Sitemap.fromJson(jsonObject); + } + + @Test + public void sitemapLabelNonNull() { + assertEquals("Main Menu", mDemoSitemapWithLabel.label()); + assertEquals("Sitemap without explicit label should return name for getLabel", + "home", mHomeSitemapWithoutLabel.label()); + } + + @Test + public void testGetLink() { + assertEquals("http://demo.openhab.org:8080/rest/sitemaps/demo", + mDemoSitemapWithLabel.link()); + assertEquals("http://demo.openhab.org:8080/rest/sitemaps/home", + mHomeSitemapWithoutLabel.link()); + } + + @Test + public void testGetHomepageLink() { + assertEquals("http://demo.openhab.org:8080/rest/sitemaps/demo/demo", + mDemoSitemapWithLabel.homepageLink()); + assertEquals("http://demo.openhab.org:8080/rest/sitemaps/home/home", + mHomeSitemapWithoutLabel.homepageLink()); + } + + @Test + public void testGetIcon() { + assertNull(mDemoSitemapWithLabel.icon()); + assertEquals("home", mHomeSitemapWithoutLabel.icon()); + } + + @Test + public void testGetName() { + assertEquals("demo", mDemoSitemapWithLabel.name()); + assertEquals("home", mHomeSitemapWithoutLabel.name()); + } +} diff --git a/mobile/src/test/java/org/openhab/habdroid/model/WidgetTest.java b/mobile/src/test/java/org/openhab/habdroid/model/WidgetTest.java new file mode 100644 index 0000000000000000000000000000000000000000..09d62758c04c7e36c916ddde5d94e4a0903728bb --- /dev/null +++ b/mobile/src/test/java/org/openhab/habdroid/model/WidgetTest.java @@ -0,0 +1,412 @@ +package org.openhab.habdroid.model; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import java.io.StringReader; +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; + +@RunWith(MockitoJUnitRunner.class) +public class WidgetTest { + private List<Widget> mSutXml = new ArrayList<>(); + private List<Widget> mSut1 = new ArrayList<>(); + private List<Widget> mSut2 = new ArrayList<>(); + private List<Widget> mSut3 = new ArrayList<>(); + + @Test + @Before + public void parse_createsWidget() throws Exception { + Widget.parseXml(mSutXml, null, createXmlNode()); + Widget.parseJson(mSut1, null, createJsonObject(1), "PNG"); + Widget.parseJson(mSut2, null, createJsonObject(2), "SVG"); + Widget.parseJson(mSut3, null, createJsonObject(3), "SVG"); + } + + @Test + public void testCountInstances() { + assertEquals(mSutXml.size(), 2); + assertEquals(mSut1.size(), 2); + assertEquals(mSut2.size(), 1); + assertEquals(mSut3.size(), 4); + } + + @Test + public void getIconPath_iconExists_returnIconUrlfromImages() { + assertEquals("images/groupicon.png", mSutXml.get(0).iconPath()); + } + + @Test + public void testGetIconPath() { + assertEquals("icon/groupicon?state=OFF&format=PNG", mSut1.get(0).iconPath()); + assertEquals("icon/groupicon?state=ON&format=SVG", mSut2.get(0).iconPath()); + assertEquals("icon/slider?state=81&format=SVG", mSut3.get(1).iconPath()); + assertEquals("Rollersutter icon must always be 0 to 100, not ON/OFF", + "icon/rollershutter?state=0&format=SVG", mSut3.get(2).iconPath()); + assertEquals("icon/rollershutter?state=42&format=SVG", mSut3.get(3).iconPath()); + } + + @Test + public void testGetChildren() { + assertEquals("demo11", mSut1.get(1).id()); + assertEquals("0202_0_0_1", mSut3.get(2).id()); + } + + @Test + public void testGetPeriod() { + assertEquals("M", mSut1.get(0).period()); + assertEquals("Object has no period, should default to 'D'", "D", mSut2.get(0).period()); + } + + @Test + public void testGetStep() { + assertEquals(1F, mSut1.get(0).step()); + // this is invalid in JSON (< 0), expected to be adjusted + assertEquals(0.1F, mSut2.get(0).step()); + } + + @Test + public void testGetRefresh() { + assertEquals(1000, mSut1.get(0).refresh()); + assertEquals("Min refresh is 100, object has set refresh to 10", + 100, mSut2.get(0).refresh()); + assertEquals("Missing refresh should equal 0", 0, mSut3.get(0).refresh()); + } + + @Test + public void testHasItem() { + assertNotNull(mSut1.get(0).item()); + assertNotNull(mSut2.get(0).item()); + } + + @Test + public void testHasLinkedPage() { + assertNotNull(mSut1.get(0).linkedPage()); + assertNull(mSut2.get(0).linkedPage()); + } + + @Test + public void testHasMappings() { + assertEquals(true, mSut1.get(0).hasMappings()); + assertEquals(true, mSut2.get(0).hasMappings()); + } + + @Test + public void testGetColors() { + assertEquals("white", mSut1.get(0).iconColor()); + assertEquals("#ff0000", mSut1.get(0).labelColor()); + assertEquals("#00ffff", mSut1.get(0).valueColor()); + assertEquals("orange", mSut2.get(0).iconColor()); + assertEquals("blue", mSut2.get(0).labelColor()); + assertEquals("red", mSut2.get(0).valueColor()); + } + + @Test + public void testGetType() { + assertEquals(Widget.Type.Group, mSut1.get(0).type()); + assertEquals(Widget.Type.Group, mSut2.get(0).type()); + assertEquals(Widget.Type.Frame, mSut3.get(0).type()); + assertEquals(Widget.Type.Switch, mSut3.get(2).type()); + assertEquals(Widget.Type.Group, mSut3.get(3).type()); + } + + @Test + public void testGetLabel() { + assertEquals("Group1", mSut1.get(0).label()); + assertEquals("Group1", mSut2.get(0).label()); + assertEquals("Dimmer [81 %]", mSut3.get(1).label()); + } + + @Test + public void testGetMappings() throws Exception { + assertEquals("ON", mSut1.get(0).mappings().get(0).value()); + assertEquals("On", mSut1.get(0).mappings().get(0).label()); + assertEquals("abcäöüßẞèéóò\uD83D\uDE03", mSut2.get(0).mappings().get(0).label()); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testGetMappingNoMapping() { + mSut3.get(1).mappings().get(0); + } + + @Test + public void testGetMinValue() { + assertEquals(0.0F, mSut1.get(0).minValue()); + assertEquals(99.7F, mSut2.get(0).minValue()); + } + + @Test + public void testGetMaxValue() { + assertEquals(10.0F, mSut1.get(0).maxValue()); + // this is invalid in JSON (max < min), expected to be adjusted + assertEquals(99.7F, mSut2.get(0).maxValue()); + } + + @Test + public void testGetUrl() { + assertEquals("http://localhost/url", mSut1.get(0).url()); + assertEquals("http://localhost/url", mSut2.get(0).url()); + assertEquals(null, mSut3.get(1).url()); + } + + @Test + public void testGetLegend() { + assertEquals(new Boolean(true), mSut1.get(0).legend()); + assertEquals(new Boolean(false), mSut2.get(0).legend()); + assertEquals(null, mSut3.get(1).legend()); + } + + @Test + public void testGetHeight() { + assertEquals(10, mSut1.get(0).height()); + assertEquals(42, mSut2.get(0).height()); + } + + @Test + public void testGetService() { + assertEquals("D", mSut1.get(0).service()); + assertEquals("XYZ", mSut2.get(0).service()); + } + + @Test + public void testGetId() { + assertEquals("demo", mSut1.get(0).id()); + assertEquals("demo", mSut2.get(0).id()); + } + + @Test + public void testGetEncoding() { + assertEquals("mpeg", mSut1.get(0).encoding()); + assertEquals(null, mSut2.get(0).encoding()); + } + + private Node createXmlNode() throws Exception { + String xml = "<widget>" + + " <widgetId>demo</widgetId>" + + " <type>Group</type>" + + " <label>Group1</label>" + + " <icon>groupicon</icon>" + + " <url>http://localhost/url</url>" + + " <minValue>0.0</minValue>" + + " <maxValue>10.0</maxValue>" + + " <step>1</step>" + + " <refresh>10</refresh>" + + " <period>D</period>" + + " <service>D</service>" + + " <height>10</height>" + + " <iconcolor>white</iconcolor>" + + " <labelcolor>white</labelcolor>" + + " <valuecolor>white</valuecolor>" + + " <encoding></encoding>" + + " <mapping>" + + " <command>ON</command>\n" + + " <label>On</label>" + + " </mapping>" + + " <item>" + + " <type>GroupItem</type>" + + " <name>group1</name>" + + " <state>Undefined</state>" + + " <link>http://localhost/rest/items/group1</link>" + + " </item>" + + " <linkedPage>" + + " <id>0001</id>" + + " <title>LinkedPage</title>" + + " <icon>linkedpageicon</icon>" + + " <link>http://localhost/rest/sitemaps/demo/0001</link>" + + " <leaf>false</leaf>" + + " </linkedPage>" + + " <widget>" + + " <widgetId>demo11</widgetId>" + + " <type>Switch</type>" + + " </widget>" + + "</widget>"; + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = dbf.newDocumentBuilder(); + Document document = builder.parse(new InputSource(new StringReader(xml))); + return document.getFirstChild(); + } + + /** + * @param id get different json objects depending on the id + * 1: All values are set + * 2: Different colors, no periode, max step size < 1, chart refresh < 100 + * 3: Frame with Slider, Rollershutter switch and Rollershutter group + * + * @return JSON object + * @throws Exception when no object with id is found + */ + private JSONObject createJsonObject(int id) throws Exception { + String json; + switch (id) { + case 1: + json = "{\n" + + " \"widgetId\": \"demo\",\n" + + " \"type\": \"Group\",\n" + + " \"label\": \"Group1\",\n" + + " \"icon\": \"groupicon\",\n" + + " \"url\": \"http://localhost/url\",\n" + + " \"minValue\": \"0.0\",\n" + + " \"maxValue\": \"10.0\",\n" + + " \"step\": \"1\",\n" + + " \"refresh\": \"1000\",\n" + + " \"period\": \"M\",\n" + + " \"service\": \"D\",\n" + + " \"height\": \"10\",\n" + + " \"legend\": \"true\",\n" + + " \"iconcolor\": \"white\",\n" + + " \"labelcolor\": \"#ff0000\",\n" + + " \"valuecolor\": \"#00ffff\",\n" + + " \"encoding\": \"mpeg\",\n" + + " \"mappings\": [{\n" + + " \"command\": \"ON\",\n" + + " \"label\": \"On\"\n" + + " }],\n" + + " \"item\": {\n" + + " \"type\": \"GroupItem\",\n" + + " \"name\": \"group1\",\n" + + " \"state\": \"OFF\",\n" + + " \"link\": \"http://localhost/rest/items/group1\"\n" + + " },\n" + + " \"linkedPage\": {\n" + + " \"id\": \"0001\",\n" + + " \"title\": \"LinkedPage\",\n" + + " \"icon\": \"linkedpageicon\",\n" + + " \"link\": \"http://localhost/rest/sitemaps/demo/0001\",\n" + + " \"leaf\": \"false\"\n" + + " },\n" + + " \"widgets\": [{ \"widgetId\": \"demo11\", \"type\": \"Switch\" }]\n" + + " }"; + break; + case 2: + json = "{\n" + + " \"widgetId\": \"demo\",\n" + + " \"type\": \"Group\",\n" + + " \"label\": \"Group1\",\n" + + " \"icon\": \"groupicon\",\n" + + " \"url\": \"http://localhost/url\",\n" + + " \"minValue\": \"99.7\",\n" + + " \"maxValue\": \"-10.0\",\n" + + " \"step\": \"-0.1\",\n" + + " \"refresh\": \"10\",\n" + + " \"service\": \"XYZ\",\n" + + " \"legend\": \"false\",\n" + + " \"height\": \"42\",\n" + + " \"iconcolor\": \"orange\",\n" + + " \"labelcolor\": \"blue\",\n" + + " \"valuecolor\": \"red\",\n" + + " \"mappings\": [{\n" + + " \"command\": \"ON\",\n" + + " \"label\": \"abcäöüßẞèéóò\uD83D\uDE03\"\n" + + " }],\n" + + " \"item\": {\n" + + " \"type\": \"Switch\",\n" + + " \"name\": \"switch1\",\n" + + " \"state\": \"ON\",\n" + + " \"link\": \"http://localhost/rest/items/switch1\"\n" + + " },\n" + + " }"; + break; + case 3: + json = "{\"widgetId\": \"0202_0\"," + + "\"type\": \"Frame\"," + + "\"label\": \"Percent-based Widgets\"," + + "\"icon\": \"frame\"," + + "\"mappings\": []," + + "\"widgets\": [" + + "{" + + "\"widgetId\": \"0202_0_0\"," + + "\"type\": \"Slider\"," + + "\"label\": \"Dimmer [81 %]\"," + + "\"icon\": \"slider\"," + + "\"mappings\": []," + + "\"switchSupport\": true," + + "\"sendFrequency\": 0," + + "\"item\": {" + + "\"link\": \"http://openhab.local:8080/rest/items/DimmedLight\"," + + "\"state\": \"81\"," + + "\"stateDescription\": {" + + "\"pattern\": \"%d %%\"," + + "\"readOnly\": false," + + "\"options\": []" + + "}," + + "\"type\": \"Dimmer\"," + + "\"name\": \"DimmedLight\"," + + "\"label\": \"Dimmer\"," + + "\"category\": \"slider\"," + + "\"tags\": []," + + "\"groupNames\": []" + + "}," + + "\"widgets\": []" + + "}," + + "{" + + "\"widgetId\": \"0202_0_0_1\"," + + "\"type\": \"Switch\"," + + "\"label\": \"Roller Shutter\"," + + "\"icon\": \"rollershutter\"," + + "\"mappings\": []," + + "\"item\": {" + + "\"link\": \"http://openhab.local:8080/rest/items/DemoShutter\"," + + "\"state\": \"0\"," + + "\"type\": \"Rollershutter\"," + + "\"name\": \"DemoShutter\"," + + "\"label\": \"Roller Shutter\"," + + "\"tags\": []," + + "\"groupNames\": [" + + "\"Shutters\"" + + "]" + + "}," + + "\"widgets\": []" + + "}," + + "{" + + "\"widgetId\": \"0202_0_0_1_2\"," + + "\"type\": \"Group\"," + + "\"label\": \"Shutters\"," + + "\"icon\": \"rollershutter\"," + + "\"mappings\": []," + + "\"item\": {" + + "\"members\": []," + + "\"groupType\": \"Rollershutter\"," + + "\"function\": {" + + "\"name\": \"AVG\"" + + "}," + + "\"link\": \"http://openhab.local:8080/rest/items/Shutters\"," + + "\"state\": \"42\"," + + "\"type\": \"Group\"," + + "\"name\": \"Shutters\"," + + "\"category\": \"rollershutter\"," + + "\"tags\": []," + + "\"groupNames\": []" + + "}," + + "\"linkedPage\": {" + + "\"id\": \"02020002\"," + + "\"title\": \"Shutters\"," + + "\"icon\": \"rollershutter\"," + + "\"link\": \"http://openhab.local:8080/rest/sitemaps/demo/02020002\"," + + "\"leaf\": true," + + "\"timeout\": false" + + "}," + + "\"widgets\": []" + + "}" + + "]" + + "}"; + break; + default: + throw new InvalidParameterException(); + } + return new JSONObject(json); + } +} diff --git a/mobile/src/test/java/org/openhab/habdroid/ui/OpenHABPreferencesActivityTest.java b/mobile/src/test/java/org/openhab/habdroid/ui/PreferencesActivityTest.java similarity index 84% rename from mobile/src/test/java/org/openhab/habdroid/ui/OpenHABPreferencesActivityTest.java rename to mobile/src/test/java/org/openhab/habdroid/ui/PreferencesActivityTest.java index 0f12e445028d13035bdac33a47ae9794cbbcfe52..80a4d2e2a8c0924b41339749abb84de00d696cf7 100644 --- a/mobile/src/test/java/org/openhab/habdroid/ui/OpenHABPreferencesActivityTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/ui/PreferencesActivityTest.java @@ -12,10 +12,10 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.openhab.habdroid.ui.OpenHABPreferencesActivity.AbstractSettingsFragment.isWeakPassword; -import static org.openhab.habdroid.ui.OpenHABPreferencesActivity.MainSettingsFragment.beautifyUrl; +import static org.openhab.habdroid.ui.PreferencesActivity.AbstractSettingsFragment.isWeakPassword; +import static org.openhab.habdroid.ui.PreferencesActivity.MainSettingsFragment.beautifyUrl; -public class OpenHABPreferencesActivityTest { +public class PreferencesActivityTest { @Test public void testIsWeakPassword() { assertTrue(isWeakPassword("")); diff --git a/mobile/src/test/java/org/openhab/habdroid/util/SyncHttpClientTest.java b/mobile/src/test/java/org/openhab/habdroid/util/SyncHttpClientTest.java index dafa25ba93b5d2711f591a74f3d5639882557407..00c1cde98cdfe197f2bd8510749dfc6ae4d90811 100644 --- a/mobile/src/test/java/org/openhab/habdroid/util/SyncHttpClientTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/util/SyncHttpClientTest.java @@ -1,5 +1,7 @@ package org.openhab.habdroid.util; +import okhttp3.OkHttpClient; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -8,8 +10,6 @@ import org.powermock.modules.junit4.PowerMockRunner; import java.net.UnknownHostException; -import okhttp3.OkHttpClient; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -24,7 +24,7 @@ public class SyncHttpClientTest { } /** - * Unit test against Issue #315 "Crash when connection could not be established" + * Unit test against Issue #315 "Crash when connection could not be established". */ @Test public void testMethodErrorResponse() { diff --git a/mobile/src/test/java/org/openhab/habdroid/util/UtilTest.java b/mobile/src/test/java/org/openhab/habdroid/util/UtilTest.java index f87d60480253253793e64549323548c5a4623581..a21a85b0b5b8c08e2f166a180f8e390f2b116b90 100644 --- a/mobile/src/test/java/org/openhab/habdroid/util/UtilTest.java +++ b/mobile/src/test/java/org/openhab/habdroid/util/UtilTest.java @@ -2,8 +2,9 @@ package org.openhab.habdroid.util; import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import org.junit.Test; -import org.openhab.habdroid.model.OpenHABSitemap; +import org.openhab.habdroid.model.Sitemap; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -24,12 +25,7 @@ import static org.junit.Assert.assertEquals; public class UtilTest { @Test - public void overridePendingTransition() throws Exception { - - } - - @Test - public void normalizeUrl() throws Exception { + public void normalizeUrl() { assertEquals("http://localhost/", Util.normalizeUrl("http://localhost/")); assertEquals("http://localhost/", Util.normalizeUrl("http://localhost")); assertEquals("http://127.0.0.1/", Util.normalizeUrl("http://127.0.0.1/")); @@ -46,7 +42,7 @@ public class UtilTest { @Test public void parseOH1SitemapList() throws Exception { - List<OpenHABSitemap> sitemapList = Util.parseSitemapList(getSitemapOH1Document()); + List<Sitemap> sitemapList = Util.parseSitemapList(getSitemapOH1Document()); assertFalse(sitemapList.isEmpty()); assertEquals("i AM DEfault", sitemapList.get(0).label()); @@ -63,7 +59,7 @@ public class UtilTest { @Test public void parseOH2SitemapListWithId1() throws Exception { - List<OpenHABSitemap> sitemapList = Util.parseSitemapList(createJsonArray(1)); + List<Sitemap> sitemapList = Util.parseSitemapList(createJsonArray(1)); assertFalse(sitemapList.isEmpty()); assertEquals("Main Menu", sitemapList.get(0).label()); @@ -72,7 +68,7 @@ public class UtilTest { @Test public void parseOH2SitemapListWithId2() throws Exception { - List<OpenHABSitemap> sitemapList = Util.parseSitemapList(createJsonArray(2)); + List<Sitemap> sitemapList = Util.parseSitemapList(createJsonArray(2)); assertFalse(sitemapList.isEmpty()); assertEquals("Main Menu", sitemapList.get(0).label()); @@ -83,7 +79,7 @@ public class UtilTest { @Test public void parseOH2SitemapListWithId3() throws Exception { - List<OpenHABSitemap> sitemapList = Util.parseSitemapList(createJsonArray(3)); + List<Sitemap> sitemapList = Util.parseSitemapList(createJsonArray(3)); assertFalse(sitemapList.isEmpty()); assertEquals("Home", sitemapList.get(0).label()); @@ -91,8 +87,9 @@ public class UtilTest { } @Test - public void testSortSitemapList() throws IOException, SAXException, ParserConfigurationException { - List<OpenHABSitemap> sitemapList = Util.parseSitemapList(getSitemapOH1Document()); + public void testSortSitemapList() + throws IOException, SAXException, ParserConfigurationException { + List<Sitemap> sitemapList = Util.parseSitemapList(getSitemapOH1Document()); Util.sortSitemapList(sitemapList, ""); // Should be sorted @@ -117,16 +114,52 @@ public class UtilTest { assertEquals("Scenes", sitemapList.get(7).label()); } - private Document getSitemapOH1Document() throws ParserConfigurationException, IOException, SAXException { - String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + - "<sitemaps><sitemap><name>default</name><label>i AM DEfault</label><link>http://myopenhab/rest/sitemaps/default</link><homepage><link>http://myopenhab/rest/sitemaps/default/default</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>heating</name><label>Heating</label><link>http://myopenhab/rest/sitemaps/heating</link><homepage><link>http://myopenhab/rest/sitemaps/heating/heating</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>lighting</name><label>Lighting</label><link>http://myopenhab/rest/sitemaps/lighting</link><homepage><link>http://myopenhab/rest/sitemaps/lighting/lighting</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>heatpump</name><label>Heatpump</label><link>http://myopenhab/rest/sitemaps/heatpump</link><homepage><link>http://myopenhab/rest/sitemaps/heatpump/heatpump</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>schedule</name><label>Schedule</label><link>http://myopenhab/rest/sitemaps/schedule</link><homepage><link>http://myopenhab/rest/sitemaps/schedule/schedule</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>outside</name><link>http://myopenhab/rest/sitemaps/outside</link><homepage><link>http://myopenhab/rest/sitemaps/outside/outside</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>garden</name><label>Garden</label><link>http://myopenhab/rest/sitemaps/garden</link><homepage><link>http://myopenhab/rest/sitemaps/garden/garden</link><leaf>false</leaf></homepage></sitemap>" + - "<sitemap><name>scenes</name><label>Scenes</label><link>http://myopenhab/rest/sitemaps/scenes</link><homepage><link>http://myopenhab/rest/sitemaps/scenes/scenes</link><leaf>false</leaf></homepage></sitemap></sitemaps>"; + private Document getSitemapOH1Document() + throws ParserConfigurationException, IOException, SAXException { + String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<sitemaps>" + + + "<sitemap><name>default</name><label>i AM DEfault</label>" + + "<link>http://myopenhab/rest/sitemaps/default</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/default/default</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>heating</name><label>Heating</label>" + + "<link>http://myopenhab/rest/sitemaps/heating</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/heating/heating</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>lighting</name><label>Lighting</label>" + + "<link>http://myopenhab/rest/sitemaps/lighting</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/lighting/lighting</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>heatpump</name><label>Heatpump</label>" + + "<link>http://myopenhab/rest/sitemaps/heatpump</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/heatpump/heatpump</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>schedule</name><label>Schedule</label>" + + "<link>http://myopenhab/rest/sitemaps/schedule</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/schedule/schedule</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>outside</name><link>http://myopenhab/rest/sitemaps/outside</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/outside/outside</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>garden</name><label>Garden</label>" + + "<link>http://myopenhab/rest/sitemaps/garden</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/garden/garden</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "<sitemap><name>scenes</name><label>Scenes</label>" + + "<link>http://myopenhab/rest/sitemaps/scenes</link>" + + "<homepage><link>http://myopenhab/rest/sitemaps/scenes/scenes</link>" + + "<leaf>false</leaf></homepage></sitemap>" + + + "</sitemaps>"; + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbf.newDocumentBuilder(); return builder.parse(new InputSource(new StringReader(xml))); @@ -137,13 +170,21 @@ public class UtilTest { public void sitemapExists() throws Exception { assertTrue(Util.sitemapExists(sitemapList(), "garden")); assertFalse(Util.sitemapExists(sitemapList(), "monkies")); - assertTrue("Sitemap \"demo\" is a \"normal\" one and exists",Util.sitemapExists(Util.parseSitemapList(createJsonArray(1)), "demo")); - assertFalse("Sitemap \"_default\" exists on the server, but isn't the only one => don't display it in the app.", Util.sitemapExists(Util.parseSitemapList(createJsonArray(1)), "_default")); - assertFalse("Sitemap \"_default\" exists on the server, but isn't the only one => don't display it in the app.", Util.sitemapExists(Util.parseSitemapList(createJsonArray(2)), "_default")); - assertTrue("Sitemap \"_default\" exists on the server and is the only one => display it in the app.", Util.sitemapExists(Util.parseSitemapList(createJsonArray(3)), "_default")); + assertTrue("Sitemap \"demo\" is a \"normal\" one and exists", + Util.sitemapExists(Util.parseSitemapList(createJsonArray(1)), "demo")); + assertFalse("Sitemap \"_default\" exists on the server, " + + "but isn't the only one => don't display it in the app.", + Util.sitemapExists(Util.parseSitemapList(createJsonArray(1)), "_default")); + assertFalse("Sitemap \"_default\" exists on the server, " + + "but isn't the only one => don't display it in the app.", + Util.sitemapExists(Util.parseSitemapList(createJsonArray(2)), "_default")); + assertTrue("Sitemap \"_default\" exists on the server " + + "and is the only one => display it in the app.", + Util.sitemapExists(Util.parseSitemapList(createJsonArray(3)), "_default")); } - private List<OpenHABSitemap> sitemapList() throws IOException, SAXException, ParserConfigurationException { + private List<Sitemap> sitemapList() + throws IOException, SAXException, ParserConfigurationException { return Util.parseSitemapList(getSitemapOH1Document()); } @@ -162,25 +203,44 @@ public class UtilTest { * @throws JSONException */ private JSONArray createJsonArray(int id) throws JSONException { - String jsonString; + JSONArray result = new JSONArray(); switch (id) { case 1: - jsonString = "[{\"name\":\"demo\",\"label\":\"Main Menu\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo/demo\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}," + - "{\"name\":\"_default\",\"label\":\"Home\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default/_default\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}]"; + result.put(createTestJsonObject("demo", "Main Menu")); + result.put(createTestJsonObject("_default", "Home")); break; case 2: - jsonString = "[{\"name\":\"demo\",\"label\":\"Main Menu\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/demo/demo\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}," + - "{\"name\":\"home\",\"label\":\"HOME\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/home/home\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}," + - "{\"name\":\"test\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/test\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/test/test\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}," + - "{\"name\":\"_default\",\"label\":\"Home\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default/_default\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}]"; + result.put(createTestJsonObject("demo", "Main Menu")); + result.put(createTestJsonObject("home", "HOME")); + result.put(createTestJsonObject("test", null)); + result.put(createTestJsonObject("_default", "Home")); break; case 3: - jsonString = "[{\"name\":\"_default\",\"label\":\"Home\",\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default\",\"homepage\":{\"link\":\"http://demo.openhab.org:8080/rest/sitemaps/_default/_default\",\"leaf\":false,\"timeout\":false,\"widgets\":[]}}]"; + result.put(createTestJsonObject("_default", "Home")); break; - default: - throw new IllegalArgumentException("Wrong id"); + default: + throw new IllegalArgumentException("Wrong id"); + } + return result; + } + + private JSONObject createTestJsonObject(String name, String label) throws JSONException { + JSONObject result = new JSONObject(); + result.put("name", name); + if (label != null) { + result.put("label", label); } - return new JSONArray(jsonString); + result.put("link", "http://demo.openhab.org:8080/rest/sitemaps/" + name); + + JSONObject homepage = new JSONObject(); + homepage.put("link", "http://demo.openhab.org:8080/rest/sitemaps/" + name + "/" + name); + homepage.put("leaf", false); + homepage.put("timeout", false); + homepage.put("widgets", new JSONArray()); + + result.put("homepage", homepage); + + return result; } @Test @@ -188,9 +248,11 @@ public class UtilTest { Exception cause = new CertPathValidatorException(); Exception e = new SSLException(cause); - assertTrue("The exception is caused by CertPathValidatorException, so testexceptionHasCause() should return true", + assertTrue("The exception is caused by CertPathValidatorException, " + + "so testexceptionHasCause() should return true", Util.exceptionHasCause(e, CertPathValidatorException.class)); - assertFalse("The exception is not caused by ArrayIndexOutOfBoundsException, so testexceptionHasCause() should return false", + assertFalse("The exception is not caused by ArrayIndexOutOfBoundsException, " + + "so testexceptionHasCause() should return false", Util.exceptionHasCause(e, ArrayIndexOutOfBoundsException.class)); } @@ -198,7 +260,8 @@ public class UtilTest { public void testObfuscateString() { assertEquals("abc***", Util.obfuscateString("abcdef")); assertEquals("abc", Util.obfuscateString("abc")); - assertEquals("The function should not throw an exception, when string length is shorter than clearTextCharCount", + assertEquals("The function should not throw an exception, " + + "when string length is shorter than clearTextCharCount", "a", Util.obfuscateString("a", 10)); assertEquals("a**", Util.obfuscateString("abc", 1)); assertEquals("***", Util.obfuscateString("abc", 0)); diff --git a/stickler/checkstyle.xml b/stickler/checkstyle.xml index 342ab4506acc760711150bfa0f44c7a3726dc993..2dc5a010b0aed6522c192663b0fd3c773b19c8f6 100644 --- a/stickler/checkstyle.xml +++ b/stickler/checkstyle.xml @@ -121,7 +121,7 @@ value="Type name ''{0}'' must match pattern ''{1}''."/> </module> <module name="MemberName"> - <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/> + <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> <message key="name.invalidPattern" value="Member name ''{0}'' must match pattern ''{1}''."/> </module> @@ -171,8 +171,9 @@ <property name="basicOffset" value="4"/> <property name="braceAdjustment" value="0"/> <property name="caseIndent" value="4"/> - <property name="throwsIndent" value="4"/> - <property name="lineWrappingIndentation" value="4"/> + <property name="throwsIndent" value="8"/> + <property name="lineWrappingIndentation" value="8"/> + <property name="forceStrictCondition" value="true"/> <property name="arrayInitIndent" value="2"/> </module> <module name="AbbreviationAsWordInName"> @@ -184,7 +185,8 @@ <module name="CustomImportOrder"> <property name="sortImportsInGroupAlphabetically" value="true"/> <property name="separateLineBetweenGroups" value="true"/> - <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/> + <property name="specialImportsRegExp" value="^android \."/> + <property name="customImportOrderRules" value="SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE###STATIC"/> </module> <module name="MethodParamPad"/> <module name="NoWhitespaceBefore">