From edb1e334309d24aa714ec81542fea7c29cf4f5ff Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 12 Feb 2017 21:20:14 -0500 Subject: [PATCH] Overhaul internal architecutre GameState objects now have Observers and are not passive objects; they also encapsulate their own parsers. The display logic is now an Observer of the GameState and everything's just a little less janky. The stage has been set for Wear integration, too, but that's not happening any time soon. --- .../ctfwstimer/lib/CtFwSGameState.java | 184 +++++++++++++++--- .../ctfwstimer/lib/CtFwSMessageFilter.java | 46 ----- mobile/build.gradle | 30 ++- mobile/proguard-rules.pro | 7 +- .../ctfwstimer/CtFwSCallbacksMQTT.java | 34 +--- ...FwSDisplay.java => CtFwSDisplayLocal.java} | 147 +++++++------- .../ctfwstimer/MainActivity.java | 20 +- .../ctfwstimer/MainActivityBuildHooks.java | 10 + mobile/src/main/res/layout/activity_main.xml | 3 +- .../MainActivityBuildHooksImpl.java | 10 + 10 files changed, 291 insertions(+), 200 deletions(-) delete mode 100644 lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSMessageFilter.java rename mobile/src/main/java/com/acmetensortoys/ctfwstimer/{CtFwSDisplay.java => CtFwSDisplayLocal.java} (70%) create mode 100644 mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooks.java create mode 100644 mobile/src/noplay/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooksImpl.java diff --git a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameState.java b/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameState.java index d86e9da..2caf7b9 100644 --- a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameState.java +++ b/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSGameState.java @@ -1,29 +1,25 @@ package com.acmetensortoys.ctfwstimer.lib; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; import java.util.Scanner; +import java.util.Set; public class CtFwSGameState { - public boolean configured; - public long startT; // NTP seconds for game start - public int setupD; - public int rounds; - public int roundD; - public long endT = 0; // NTP seconds for game end (if >= startT) - public int flagsTotal; - public boolean flagsVisible = false; - public int flagsRed = 0; - public int flagsYel = 0; + // Game time - public void setFlags(boolean visible) { - flagsVisible = visible; - } - public void setFlags(int red, int yel) { - flagsRed = red; flagsYel = yel; - } + private boolean configured = false; + private long startT; // NTP seconds for game start + private int setupD; + private int rounds; + private int roundD; + private long endT = 0; // NTP seconds for game end (if >= startT) - public void mqttConfigMessage(String st) { + public void fromMqttConfigMessage(String st) { String tm = st.trim(); switch (tm) { case "none": @@ -43,29 +39,33 @@ public class CtFwSGameState { } break; } + if (!isMessageTimeWithin(lastMsgTimestamp)) { + msgs.clear(); + notifyMessages(); + } + notifyConfig(); } - public void mqttFlagsMessage(String st) { - String tm = st.trim(); - switch(tm) { - case "?": - this.setFlags(false); - break; - default: - Scanner s = new Scanner(tm); - try { - this.setFlags(true); - this.setFlags(s.nextInt(),s.nextInt()); - } catch (NumberFormatException e) { - this.setFlags(false); - } + public String toMqttConfigMessage() { + if (!configured) { + return "none"; } + + return String.format(Locale.ROOT, "%d %d %d %d %d", startT, setupD, rounds, roundD, flagsTotal); + } + public void deconfigure() { + this.configured = false; + notifyConfig(); + } + public void setEndT(long endT) { + this.endT = endT; + notifyConfig(); } public class Now { public String rationale = null; // null if game is in play, otherwise other fields invalid + public boolean stop = false; public int round = 0; // 0 for setup public long roundStart = 0, roundEnd = 0; // NTP seconds - public boolean stop = false; } public Now getNow(long now) { Now res = new Now(); @@ -77,6 +77,7 @@ public class CtFwSGameState { res.stop = true; } else if (now <= startT) { res.rationale = "Start time in the future!"; + res.roundStart = startT; } if (res.rationale != null) { return res; @@ -100,4 +101,123 @@ public class CtFwSGameState { res.round += 1; return res; } + public boolean isConfigured(){ + return configured; + } + public long getStartT() { return startT; } + public long getFirstRoundStartT() { return startT + setupD; } + public int getRounds() { return rounds; } + public int getComputedGameDuration() { return rounds * roundD ; } + + // Leaves off the natural endT comparison so that messages can be posted after the + // game ends and still count as part of this one (i.e. still be displayed). + private boolean isMessageTimeWithin(long time) { + return !configured || time >= startT; + } + + // Game score + + public int flagsTotal; + public boolean flagsVisible = false; + public int flagsRed = 0; + public int flagsYel = 0; + + public void fromMqttFlagsMessage(String st) { + String tm = st.trim(); + switch(tm) { + case "?": + flagsVisible = false; + break; + default: + Scanner s = new Scanner(tm); + try { + flagsVisible = true; + int red = s.nextInt(); + int yel = s.nextInt(); + flagsRed = red; + flagsYel = yel; + } catch (NumberFormatException e) { + flagsVisible = false; + } + } + notifyFlags(); + } + public String toMqttFlagsMessage() { + if (!configured || !flagsVisible) { + return "?"; + } + + return String.format(Locale.ROOT, "%d %d", flagsRed, flagsYel); + } + + // Informative messages handling + + public class Msg { + public long when; + public String msg; + + Msg(long when, String msg) { + this.when = when; + this.msg = msg; + } + } + private List msgs = new ArrayList<>(); + private long lastMsgTimestamp; + + public void onNewMessage(String str) { + Scanner s = new Scanner(str); + long t; + + try { + t = s.nextLong(); + } catch (NoSuchElementException nse) { + // Maybe they forgot a time stamp. That's not ideal, but... fake it? + // XXX Back off a bit, for time sync reasons + lastMsgTimestamp = System.currentTimeMillis()/1000 - 30; + msgs.add(new Msg(lastMsgTimestamp, str)); + notifyMessages(); + return; + } + + // If there is no configuration, assume the message is new enough + // If there *is* a configuration, check the time. + if (isMessageTimeWithin(t) && (lastMsgTimestamp <= t)) { + s.useDelimiter("\\z"); + lastMsgTimestamp = t; + msgs.add(new Msg(lastMsgTimestamp, s.next().trim())); + notifyMessages(); + } + } + + // Observer interface + + public interface Observer { + void onCtFwSConfigure(CtFwSGameState game); + void onCtFwSFlags(CtFwSGameState game); + void onCtFwSMessage(CtFwSGameState game, List msgs); + + } + final private Set mObsvs = new HashSet<>(); + private void notifyFlags() { + synchronized(this) { + for (Observer o : mObsvs) { o.onCtFwSFlags(this); } + } + } + private void notifyMessages() { + synchronized(this) { + for (Observer o : mObsvs) { o.onCtFwSMessage(this, msgs); } + } + } + private void notifyConfig() { + synchronized(this) { + for (Observer o : mObsvs) { o.onCtFwSConfigure(this); } + } + } + public void registerObserver(Observer d) { + synchronized(this) { mObsvs.add(d); } + } + public void unregisterObserver(Observer d) { + synchronized(this) { mObsvs.remove(d); } + } + } diff --git a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSMessageFilter.java b/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSMessageFilter.java deleted file mode 100644 index be919df..0000000 --- a/lib/src/main/java/com/acmetensortoys/ctfwstimer/lib/CtFwSMessageFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.acmetensortoys.ctfwstimer.lib; - -import java.util.NoSuchElementException; -import java.util.Scanner; - -public class CtFwSMessageFilter { - final private CtFwSGameState mCgs; - public CtFwSMessageFilter(CtFwSGameState cgs) { - mCgs = cgs; - } - - public class Msg { - public long when; - public String msg; - - public Msg(long when, String msg) { - this.when = when; - this.msg = msg; - } - } - - private long lastMsgTimestamp = 0; - - public Msg filter(String str) { - Scanner s = new Scanner(str); - long t; - try { - t = s.nextLong(); - } catch (NoSuchElementException nse) { - // Maybe they forgot a time stamp. That's not ideal, but... fake it? - // XXX Back off a bit, for time sync reasons - lastMsgTimestamp = System.currentTimeMillis()/1000 - 30; - return new Msg(lastMsgTimestamp, str); - } - - // If there is no configuration, assume the message is new enough - // If there *is* a configuration, check the time. - if ((!mCgs.configured || t >= mCgs.startT) && (lastMsgTimestamp <= t)) { - s.useDelimiter("\\z"); - lastMsgTimestamp = t; - return new Msg(lastMsgTimestamp, s.next().trim()); - } - - return null; - } -} diff --git a/mobile/build.gradle b/mobile/build.gradle index b4c4015..7a763c9 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -2,18 +2,18 @@ apply plugin: 'com.android.application' android { compileSdkVersion 25 - buildToolsVersion "24.0.3" + buildToolsVersion "25.0.2" defaultConfig { applicationId "com.acmetensortoys.ctfwstimer" minSdkVersion 19 - targetSdkVersion 24 + targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { - minifyEnabled false + minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { @@ -21,11 +21,21 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + flavorDimensions "play" + productFlavors { + noplay { + dimension "play" + } + play { + dimension "play" + } + } } repositories { maven { - url "https://repo.eclipse.org/content/repositories/paho-releases/" + url "https://repo.eclipse.org/content/repositories/paho-snapshots/" } } @@ -38,11 +48,15 @@ dependencies { compile project(":lib") - compile('org.eclipse.paho:org.eclipse.paho.android.service:1.1.1') { - exclude module: 'support-v4' - } compile 'com.android.support:appcompat-v7:25.1.1' - compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' compile 'com.android.support:support-v4:25.1.1' + + playCompile 'com.google.android.gms:play-services:10.0.1' + + compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1-SNAPSHOT' + compile('org.eclipse.paho:org.eclipse.paho.android.service:1.1.2-SNAPSHOT') { + exclude module: 'support-v4' + } + testCompile 'junit:junit:4.12' } diff --git a/mobile/proguard-rules.pro b/mobile/proguard-rules.pro index 4e7b00d..5538e6c 100644 --- a/mobile/proguard-rules.pro +++ b/mobile/proguard-rules.pro @@ -14,9 +14,4 @@ # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; -#} - -# Work around some Paho packaging warnings that manifest as errors. -# See http://github.com/eclipse/paho.mqtt.android/issues/79 --keepattributes InnerClasses --dontoptimize \ No newline at end of file +#} \ No newline at end of file diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSCallbacksMQTT.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSCallbacksMQTT.java index 30e43df..27d06e4 100644 --- a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSCallbacksMQTT.java +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSCallbacksMQTT.java @@ -3,23 +3,15 @@ package com.acmetensortoys.ctfwstimer; import android.util.Log; import com.acmetensortoys.ctfwstimer.lib.CtFwSGameState; -import com.acmetensortoys.ctfwstimer.lib.CtFwSMessageFilter; import org.eclipse.paho.client.mqttv3.IMqttMessageListener; import org.eclipse.paho.client.mqttv3.MqttMessage; -import java.util.NoSuchElementException; -import java.util.Scanner; - class CtFwSCallbacksMQTT { - final private CtFwSDisplay mCdl; final private CtFwSGameState mCgs; - final private CtFwSMessageFilter mCmf; - CtFwSCallbacksMQTT(CtFwSDisplay cdl, CtFwSGameState cgs) { - mCdl = cdl; + CtFwSCallbacksMQTT(CtFwSGameState cgs) { mCgs = cgs; - mCmf = new CtFwSMessageFilter(mCgs); } IMqttMessageListener onConfig = new IMqttMessageListener() { @@ -27,8 +19,7 @@ class CtFwSCallbacksMQTT { public void messageArrived(String topic, MqttMessage message) throws Exception { String tm = message.toString().trim(); Log.d("CtFwS", "Message(Config): " + tm); - mCgs.mqttConfigMessage(tm); - mCdl.notifyGameState(); + mCgs.fromMqttConfigMessage(tm); } }; @@ -36,12 +27,13 @@ class CtFwSCallbacksMQTT { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { Log.d("CtFwS", "Message(End): " + message); + long endT; try { - mCgs.endT = Long.parseLong(message.toString()); + endT = Long.parseLong(message.toString()); } catch (NumberFormatException e) { - mCgs.endT = 0; + endT = 0; } - mCdl.notifyGameState(); + mCgs.setEndT(endT); } }; @@ -50,24 +42,16 @@ class CtFwSCallbacksMQTT { public void messageArrived(String topic, MqttMessage message) throws Exception { String tm = message.toString().trim(); Log.d("CtFwS", "Message(Flags): " + tm); - mCgs.mqttFlagsMessage(tm); - mCdl.notifyFlags(); + mCgs.fromMqttFlagsMessage(tm); } }; - private void onMessageCommon(String str) { - CtFwSMessageFilter.Msg m = mCmf.filter(str); - if (m != null) { - mCdl.notifyMessage(m.when, m.msg); - } - } - IMqttMessageListener onMessage = new IMqttMessageListener() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { String str = message.toString(); Log.d("CtFwS", "Message(Broadcast): " + str); - onMessageCommon(str); + mCgs.onNewMessage(str); } }; @@ -76,7 +60,7 @@ class CtFwSCallbacksMQTT { public void messageArrived(String topic, MqttMessage message) throws Exception { String str = message.toString(); Log.d("CtFwS", "Message(Players): " + str); - onMessageCommon(str); + mCgs.onNewMessage(str); } }; } diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplay.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java similarity index 70% rename from mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplay.java rename to mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java index f4b9adc..a89eabf 100644 --- a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplay.java +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/CtFwSDisplayLocal.java @@ -5,40 +5,43 @@ import android.os.Handler; import android.os.SystemClock; import android.text.format.DateUtils; import android.util.Log; +import android.view.View; import android.widget.Chronometer; import android.widget.ProgressBar; import android.widget.TextView; import com.acmetensortoys.ctfwstimer.lib.CtFwSGameState; -// TODO nwf is bad at UI design; someone who isn't him should improve this +import java.util.List; + +import static android.view.View.INVISIBLE; -class CtFwSDisplay { +// TODO nwf is bad at UI design; someone who isn't him should improve this +class CtFwSDisplayLocal implements CtFwSGameState.Observer { final private Activity mAct; final private Handler mHandler; - final private CtFwSGameState mCgs; - private long lastMsgTimeMS = 0; - - CtFwSDisplay(Activity a, Handler h, CtFwSGameState cgs) { + CtFwSDisplayLocal(Activity a, Handler h) { mAct = a; mHandler = h; - mCgs = cgs; } - final private Runnable mProber = new Runnable() { - @Override - public void run() { - notifyGameState(); - } - }; + private Runnable mProber; - void notifyGameState() { + @Override + public void onCtFwSConfigure(final CtFwSGameState gs) { final long nowMS = System.currentTimeMillis(); long nowET = SystemClock.elapsedRealtime(); // Chronometer timebase final long tbcf = nowMS - nowET; // time base correction factor ("when we booted"-ish) - final CtFwSGameState.Now now = mCgs.getNow(nowMS / 1000); + final CtFwSGameState.Now now = gs.getNow(nowMS / 1000); + final Runnable prober = new Runnable() { + @Override + public void run() { + onCtFwSConfigure(gs); + } + }; + Log.d("CtFwS", "Display game state; nowMS=" + nowMS + " r=" + now.round + " rs=" + now.roundStart + " re=" + now.roundEnd); @@ -49,9 +52,12 @@ class CtFwSDisplay { doReset(); - mHandler.removeCallbacks(mProber); + if (mProber != null) { + mHandler.removeCallbacks(mProber); + } if (!now.stop) { - mHandler.postDelayed(mProber, mCgs.startT*1000 - nowMS); + mProber = prober; + mHandler.postDelayed(mProber, now.roundStart*1000 - nowMS); } return; @@ -59,12 +65,11 @@ class CtFwSDisplay { // Otherwise, it's game on! - // Clear the mesage log if it looks like it's a new game in play - if (lastMsgTimeMS < mCgs.startT * 1000) { - clearMsgs(); - } - + // Schedule a callback around the time of the next round; if we're early, + // that's fine, we'll schedule it again. If we're late, it'll be glitchy, + // but that's fine. mHandler.removeCallbacks(mProber); + mProber = prober; mHandler.postDelayed(mProber, now.roundEnd * 1000 - nowMS); { @@ -74,7 +79,7 @@ class CtFwSDisplay { public void run() { if (now.round == 0) { tv_jb.setText(R.string.ctfws_gamestart); - } else if (now.round == mCgs.rounds) { + } else if (now.round == gs.getRounds()) { tv_jb.setText(R.string.ctfws_gameend); } else { tv_jb.setText( @@ -89,11 +94,7 @@ class CtFwSDisplay { @Override public void run() { pb_jb.setIndeterminate(false); - if (now.round == 0) { - pb_jb.setMax(mCgs.setupD - 1); - } else { - pb_jb.setMax(mCgs.roundD - 1); - } + pb_jb.setMax((int)(now.roundEnd - now.roundStart)); pb_jb.setProgress(0); } }); @@ -102,11 +103,11 @@ class CtFwSDisplay { ch_jb.post(new Runnable() { @Override public void run() { - ch_jb.setBase(now.roundEnd * 1000 - tbcf); + ch_jb.setBase((now.roundEnd + 1) * 1000 - tbcf); ch_jb.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { @Override public void onChronometerTick(Chronometer c) { - pb_jb.setProgress((int)(now.roundEnd - System.currentTimeMillis()/1000) - 1); + pb_jb.setProgress((int)(now.roundEnd - System.currentTimeMillis()/1000)); } }); ch_jb.start(); @@ -119,7 +120,7 @@ class CtFwSDisplay { @Override public void run() { pb_gp.setIndeterminate(false); - pb_gp.setMax(mCgs.rounds * mCgs.roundD - 1); + pb_gp.setMax(gs.getComputedGameDuration()); pb_gp.setProgress(0); } }); @@ -128,14 +129,15 @@ class CtFwSDisplay { ch_gp.post(new Runnable() { @Override public void run() { - ch_gp.setBase((mCgs.startT + mCgs.setupD) * 1000 - tbcf); + ch_gp.setBase(gs.getFirstRoundStartT() * 1000 - tbcf); ch_gp.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { @Override public void onChronometerTick(Chronometer c) { pb_gp.setProgress((int)(System.currentTimeMillis()/1000 - - mCgs.startT - mCgs.setupD)); + - gs.getFirstRoundStartT())); } }); + ch_gp.setVisibility(View.VISIBLE); ch_gp.start(); } }); @@ -144,9 +146,7 @@ class CtFwSDisplay { pb_gp.post(new Runnable() { @Override public void run() { - pb_gp.setIndeterminate(false); - pb_gp.setMax(mCgs.rounds * mCgs.roundD - 1); - pb_gp.setProgress(0); + pb_gp.setIndeterminate(true); } }); @@ -154,9 +154,8 @@ class CtFwSDisplay { ch_gp.post(new Runnable() { @Override public void run() { - ch_gp.setBase(nowMS - tbcf); - ch_gp.setOnChronometerTickListener(null); ch_gp.stop(); + ch_gp.setVisibility(INVISIBLE); } }); } @@ -166,8 +165,7 @@ class CtFwSDisplay { @Override public void run() { tv_flags.setText( - String.format(mAct.getResources().getString(R.string.ctfws_flags), - mCgs.flagsTotal)); + String.format(mAct.getResources().getString(R.string.ctfws_flags), gs.flagsTotal)); } }); } @@ -192,11 +190,9 @@ class CtFwSDisplay { ch.post(new Runnable() { @Override public void run() { - ch.setOnChronometerTickListener(null); - ch.setBase(SystemClock.elapsedRealtime()); ch.stop(); - } - }); + ch.setVisibility(View.INVISIBLE); + }}); } { final ProgressBar pb = (ProgressBar) (mAct.findViewById(R.id.pb_jailbreak)); @@ -218,16 +214,17 @@ class CtFwSDisplay { } } - void notifyFlags() { + @Override + public void onCtFwSFlags(CtFwSGameState gs) { // TODO: This stinks final StringBuffer sb = new StringBuffer(); - if (mCgs.configured) { - if (mCgs.flagsVisible) { + if (gs.isConfigured()) { + if (gs.flagsVisible) { sb.append("r="); - sb.append(mCgs.flagsRed); + sb.append(gs.flagsRed); sb.append(" y="); - sb.append(mCgs.flagsYel); + sb.append(gs.flagsYel); } else { sb.append("r=? y=?"); } @@ -242,30 +239,36 @@ class CtFwSDisplay { }); } - void clearMsgs() { - final TextView msgs = (TextView) (mAct.findViewById(R.id.msgs)); - msgs.post(new Runnable() { - @Override - public void run() { - msgs.setText(""); - } - }); - } + @Override + public void onCtFwSMessage(CtFwSGameState gs, List msgs) { + final TextView msgstv = (TextView)(mAct.findViewById(R.id.msgs)); + int s = msgs.size(); - void notifyMessage(long ts, String m) { - final StringBuffer sb = new StringBuffer(); - long td = (ts == 0) ? 0 : (mCgs.configured) ? ts - mCgs.startT : 0; - sb.append(DateUtils.formatElapsedTime(td)); - sb.append(": "); - sb.append(m); - sb.append("\n"); + if (s == 0) { + msgstv.post(new Runnable() { + @Override + public void run() { + msgstv.setText(""); + } + }); + } else { - final TextView msgs = (TextView)(mAct.findViewById(R.id.msgs)); - msgs.post(new Runnable() { - @Override - public void run() { - msgs.append(sb); - } - }); + CtFwSGameState.Msg m = msgs.get(s - 1); + + long td = (m.when == 0) ? 0 : (gs.isConfigured()) ? m.when - gs.getStartT() : 0; + + final StringBuffer sb = new StringBuffer(); + sb.append(DateUtils.formatElapsedTime(td)); + sb.append(": "); + sb.append(m.msg); + sb.append("\n"); + + msgstv.post(new Runnable() { + @Override + public void run() { + msgstv.append(sb); + } + }); + } } } diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java index 83599b9..277ce42 100644 --- a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivity.java @@ -17,13 +17,11 @@ import android.view.View; import android.widget.TextView; import org.eclipse.paho.android.service.MqttAndroidClient; -import org.eclipse.paho.android.service.MqttTraceHandler; import org.eclipse.paho.client.mqttv3.IMqttActionListener; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.IMqttToken; import org.eclipse.paho.client.mqttv3.MqttCallbackExtended; import org.eclipse.paho.client.mqttv3.MqttClient; -import org.eclipse.paho.client.mqttv3.MqttClientPersistence; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; @@ -35,9 +33,10 @@ public class MainActivity extends AppCompatActivity { private MqttAndroidClient mMqc; private final CtFwSGameState mCgs = new CtFwSGameState(); - private CtFwSDisplay mCdl; // set in onCreate private CtFwSCallbacksMQTT mCtfwscbs ; // set in onCreate + private MainActivityBuildHooks mabh = new MainActivityBuildHooksImpl(); + private TextView mTvSU; // set in onCreate private TextView mTvSS; // set in onCreate private void setServerStateText(@StringRes final int resid) { @@ -120,14 +119,12 @@ public class MainActivity extends AppCompatActivity { public void onSuccess(IMqttToken asyncActionToken) { Log.d("CtFwS", "Conn OK 1"); setServerStateText(R.string.mqtt_conn); - mCdl.clearMsgs(); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.e("CtFws", "Conn Fail", exception); setServerStateText(R.string.mqtt_disconn); - mCdl.clearMsgs(); } }; @@ -145,8 +142,7 @@ public class MainActivity extends AppCompatActivity { } } mMqc = null; - mCgs.configured = false; - mCdl.notifyGameState(); + mCgs.deconfigure(); } // If that's all we were told to do, we're done @@ -206,7 +202,7 @@ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { - String defserver = "tcp://nwf1.xen.prgmr.com:1883"; + String defserver = "tcp://ctfws-mqtt.ietfng.org:1883"; super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); @@ -214,8 +210,12 @@ public class MainActivity extends AppCompatActivity { mTvSU = (TextView) findViewById(R.id.tv_mqtt_server_uri); mTvSS = (TextView) findViewById(R.id.tv_mqtt_state); - mCdl = new CtFwSDisplay(this, new Handler(), mCgs); - mCtfwscbs = new CtFwSCallbacksMQTT(mCdl, mCgs); + CtFwSDisplayLocal mCdl = new CtFwSDisplayLocal(this, new Handler()); + mCgs.registerObserver(mCdl); + + mabh.onCreate(mCgs); + + mCtfwscbs = new CtFwSCallbacksMQTT(mCgs); SharedPreferences sp = getPreferences(MODE_PRIVATE); if (sp.getString("server", null) == null) { diff --git a/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooks.java b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooks.java new file mode 100644 index 0000000..63bea17 --- /dev/null +++ b/mobile/src/main/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooks.java @@ -0,0 +1,10 @@ +package com.acmetensortoys.ctfwstimer; + +import com.acmetensortoys.ctfwstimer.lib.CtFwSGameState; + +// The MainActivity expects a "MainActivityBuildHooksImpl" class that ascribes to this interface +// per build flavor. This will be used when, for example, we kick on Google Play for Wear +// interaction and want to push messages out to the wearable data network. +interface MainActivityBuildHooks { + void onCreate(CtFwSGameState cgs); +} diff --git a/mobile/src/main/res/layout/activity_main.xml b/mobile/src/main/res/layout/activity_main.xml index 952f7a4..f6c88f2 100644 --- a/mobile/src/main/res/layout/activity_main.xml +++ b/mobile/src/main/res/layout/activity_main.xml @@ -132,7 +132,8 @@ + android:id="@+id/ch_gameProgress" + android:visibility="invisible" /> diff --git a/mobile/src/noplay/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooksImpl.java b/mobile/src/noplay/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooksImpl.java new file mode 100644 index 0000000..88b0d04 --- /dev/null +++ b/mobile/src/noplay/java/com/acmetensortoys/ctfwstimer/MainActivityBuildHooksImpl.java @@ -0,0 +1,10 @@ +package com.acmetensortoys.ctfwstimer; + +import com.acmetensortoys.ctfwstimer.lib.CtFwSGameState; + +public class MainActivityBuildHooksImpl implements MainActivityBuildHooks { + @Override + public void onCreate(CtFwSGameState cgs) { + // No-op + } +} \ No newline at end of file -- 2.50.1