diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
index 73583189f..b6a5310e0 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java
@@ -2745,7 +2745,7 @@ public class BoardDelegate extends DelegateBase
}
}
if ( m_connTypes.contains( CommsConnType.COMMS_CONN_RELAY ) ) {
- if ( !RelayService.relayEnabled( m_activity ) ) {
+ if ( !XWPrefs.getRelayEnabled( m_activity ) ) {
m_dropRelayOnDismiss = false;
String msg = getString( R.string.warn_relay_disabled )
+ "\n\n" + getString( R.string.warn_relay_remove );
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java
index 2912096b0..0d4d7993c 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnStatusHandler.java
@@ -680,7 +680,7 @@ public class ConnStatusHandler {
//!getAirplaneModeOn( context );
break;
case COMMS_CONN_RELAY:
- result = RelayService.relayEnabled( context )
+ result = XWPrefs.getRelayEnabled( context )
&& NetStateCache.netAvail( context );
break;
case COMMS_CONN_P2P:
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java
index bea4e8fea..2a0bca05c 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/ConnViaViewLayout.java
@@ -125,7 +125,7 @@ public class ConnViaViewLayout extends LinearLayout {
enabled = BTService.BTEnabled();
break;
case COMMS_CONN_RELAY:
- enabled = RelayService.relayEnabled( context );
+ enabled = XWPrefs.getRelayEnabled( context );
break;
case COMMS_CONN_P2P:
enabled = WiDirWrapper.enabled();
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java
index d29cce2b3..da5b5cacc 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java
@@ -370,10 +370,6 @@ public class DBUtils {
if ( null != summary ) { // nag time may have changed
NagTurnReceiver.setNagTimer( context );
}
-
- if ( needsTimer ) {
- RelayTimerReceiver.setTimer( context );
- }
} // saveSummary
public static void addRematchInfo( Context context, long rowid, String btAddr,
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java
index 8fc7267ac..9877ab87c 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java
@@ -433,6 +433,7 @@ public class DlgDelegate {
makeOkOnlyBuilder( R.string.no_games_to_refresh ).show();
} else {
RelayService.timerFired( m_activity );
+ MQTTUtils.timerFired( m_activity );
Utils.showToast( m_activity, R.string.msgs_progress );
}
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java
index 7612af656..34ff8e7fa 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java
@@ -82,6 +82,19 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
getOrStart( context );
}
+ public static void timerFired( Context context )
+ {
+ MQTTUtils instance;
+ synchronized ( sInstance ) {
+ instance = sInstance[0];
+ }
+
+ if ( null != instance && !instance.isConnected() ) {
+ clearInstance( instance );
+ }
+ getOrStart( context ); // no-op if have instance
+ }
+
static void onConfigChanged( Context context )
{
MQTTUtils instance;
@@ -160,6 +173,16 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
now - startTime );
}
+ private boolean isConnected()
+ {
+ MqttAsyncClient client = mClient;
+ boolean result = null != client
+ && client.isConnected()
+ && mState != State.CLOSING;
+ Log.d( TAG, "isConnected() => %b", result );
+ return result;
+ }
+
private void enqueue( String topic, byte[] packet )
{
mOutboundQueue.add( new MessagePair( topic, packet ) );
@@ -435,6 +458,8 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
mMsgThread.add( message.getPayload() );
ConnStatusHandler
.updateStatusIn( mContext, CommsConnType.COMMS_CONN_MQTT, true );
+
+ RelayTimerReceiver.restartBackoff( mContext, TAG );
}
@Override
@@ -443,6 +468,7 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba
Log.d( TAG, "%H.deliveryComplete(token=%s)", this, token );
ConnStatusHandler
.updateStatusOut( mContext, CommsConnType.COMMS_CONN_MQTT, true );
+ RelayTimerReceiver.restartBackoff( mContext, TAG );
}
private void subscribe()
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OnBootReceiver.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OnBootReceiver.java
index dcff3fe47..16152b68a 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OnBootReceiver.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/OnBootReceiver.java
@@ -45,7 +45,7 @@ public class OnBootReceiver extends BroadcastReceiver {
protected static void startTimers( Context context )
{
NagTurnReceiver.restartTimer( context );
- RelayTimerReceiver.setTimer( context );
+ RelayTimerReceiver.setTimer( context, true );
SMSResendReceiver.setTimer( context );
}
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PollListPreference.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PollListPreference.java
deleted file mode 100644
index 2c69c7514..000000000
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/PollListPreference.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- compile-command: "find-and-gradle.sh inXw4dDeb"; -*- */
-/*
- * Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
- * rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package org.eehouse.android.xw4;
-
-import android.content.Context;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.util.AttributeSet;
-
-
-public class PollListPreference extends ListPreference
- implements Preference.OnPreferenceChangeListener {
-
- private Context m_context;
-
- public PollListPreference( Context context, AttributeSet attrs )
- {
- super( context, attrs );
- m_context = context;
- setOnPreferenceChangeListener( this );
- }
-
- @Override
- protected void onAttachedToActivity()
- {
- String val = getPersistedString( "0" );
- setSummaryToMatch( val );
- }
-
- // Preference.OnPreferenceChangeListener interface
- public boolean onPreferenceChange( Preference preference, Object newValue )
- {
- String valstr = (String)newValue;
- int val = Integer.parseInt(valstr);
- RelayTimerReceiver.setTimer( m_context, val * 1000 );
-
- setSummaryToMatch( valstr );
- return true;
- }
-
- private void setSummaryToMatch( String value )
- {
- int index = findIndexOfValue( value );
- if ( 0 <= index ) {
- CharSequence entry = getEntries()[index];
- setSummary( entry );
- }
- }
-}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
index 5e47cc29f..124fc5615 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
@@ -192,16 +192,8 @@ public class RelayService extends XWJIService
return s_lastFCM;
}
- public static boolean relayEnabled( Context context )
- {
- boolean enabled = ! XWPrefs
- .getPrefsBoolean( context, R.string.key_disable_relay, false );
- // Log.d( TAG, "relayEnabled() => %b", enabled );
- return enabled;
- }
-
public static void enabledChanged( Context context ) {
- boolean enabled = relayEnabled( context );
+ boolean enabled = XWPrefs.getRelayEnabled( context );
if ( enabled ) {
startService( context );
} else {
@@ -421,13 +413,6 @@ public class RelayService extends XWJIService
}
}
- if ( shouldMaintainConnection() ) {
- long interval_millis = getMaxIntervalSeconds() * 1000;
- RelayTimerReceiver.setTimer( this, interval_millis );
- // Log.d( TAG, "onDestroy(): rescheduling in %d ms",
- // interval_millis );
- }
-
super.onDestroy();
// Log.d( TAG, "%s.onDestroy() DONE", this );
}
@@ -517,7 +502,6 @@ public class RelayService extends XWJIService
} else if ( registerWithRelayIfNot( timestamp ) ) {
requestMessages( timestamp );
}
- RelayTimerReceiver.setTimer( this );
break;
case STOP:
stopThreads();
@@ -781,7 +765,7 @@ public class RelayService extends XWJIService
private boolean startFetchThreadIfNotUDP()
{
// DbgUtils.logf( "startFetchThreadIfNotUDP()" );
- boolean handled = relayEnabled( this ) && !BuildConfig.UDP_ENABLED;
+ boolean handled = XWPrefs.getRelayEnabled( this ) && !BuildConfig.UDP_ENABLED;
if ( handled && null == m_fetchThread ) {
Assert.failDbg(); // NOT using this now!
@@ -814,7 +798,7 @@ public class RelayService extends XWJIService
private UDPReadThread startUDPReadThreadOnce()
{
UDPReadThread thread = null;
- if ( BuildConfig.UDP_ENABLED && relayEnabled( this ) ) {
+ if ( BuildConfig.UDP_ENABLED && XWPrefs.getRelayEnabled( this ) ) {
synchronized ( sUDPReadThreadRef ) {
thread = sUDPReadThreadRef.get();
if ( null == thread ) {
@@ -997,6 +981,7 @@ public class RelayService extends XWJIService
private void gotPacket( DatagramPacket packet )
{
ConnStatusHandler.showSuccessIn();
+ RelayTimerReceiver.restartBackoff( this, TAG );
int packetLen = packet.getLength();
byte[] data = new byte[packetLen];
@@ -1007,7 +992,7 @@ public class RelayService extends XWJIService
private boolean shouldRegister()
{
- boolean should = relayEnabled( this );
+ boolean should = XWPrefs.getRelayEnabled( this );
if ( should ) {
String relayID = DevID.getRelayDevID( this, true );
boolean registered = null != relayID;
@@ -1588,7 +1573,7 @@ public class RelayService extends XWJIService
private void startThreads()
{
Log.d( TAG, "startThreads()" );
- if ( !relayEnabled( this ) || !NetStateCache.netAvail( this ) ) {
+ if ( !XWPrefs.getRelayEnabled( this ) || !NetStateCache.netAvail( this ) ) {
stopThreads();
} else if ( BuildConfig.UDP_ENABLED ) {
stopFetchThreadIf();
@@ -1720,7 +1705,7 @@ public class RelayService extends XWJIService
private boolean shouldMaintainConnection()
{
- boolean result = relayEnabled( this )
+ boolean result = XWPrefs.getRelayEnabled( this )
&& (0 == s_lastFCM || XWPrefs.getIgnoreFCM( this ));
if ( result ) {
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayTimerReceiver.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayTimerReceiver.java
index 60235b656..efa4735e8 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayTimerReceiver.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayTimerReceiver.java
@@ -29,36 +29,65 @@ import android.os.SystemClock;
public class RelayTimerReceiver extends BroadcastReceiver {
private static final String TAG = RelayTimerReceiver.class.getSimpleName();
+ private static final String KEY_BACKOFF = TAG + "/backoff";
+ private static final String KEY_NEXT_BACKOFF = TAG + "/next_backoff";
+ private static final long MIN_BACKOFF = 1000 * 10; // 10 seconds
+ private static final long MAX_BACKOFF = 1000 * 60 * 60 * 32; // 23 hours
@Override
public void onReceive( Context context, Intent intent )
{
Log.d( TAG, "onReceive(intent=%s)", intent );
RelayService.timerFired( context );
- }
+ MQTTUtils.timerFired( context );
- public static void setTimer( Context context )
- {
- setTimer( context, 1000 * 1800 ); // to be changed shortly
- }
-
- public static void setTimer( Context context, long interval_millis )
- {
- AlarmManager am =
- (AlarmManager)context.getSystemService( Context.ALARM_SERVICE );
-
- Intent intent = new Intent( context, RelayTimerReceiver.class );
- PendingIntent pi = PendingIntent.getBroadcast( context, 0, intent, 0 );
-
- // Check if we have any relay IDs, since we'll be using them to
- // identify connected games for which we can fetch messages
- if ( interval_millis > 0 && DBUtils.haveRelayIDs( context ) ) {
- long fire_millis = SystemClock.elapsedRealtime() + interval_millis;
- am.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, fire_millis, pi );
+ long nextBackoff = DBUtils.getLongFor( context, KEY_BACKOFF, MIN_BACKOFF );
+ if ( nextBackoff == MAX_BACKOFF ) {
+ // at max, so no change and nothing to save
} else {
- // will happen if user's set getProxyIntervalSeconds to return 0
- am.cancel( pi );
+ nextBackoff *= 2;
+ if ( nextBackoff > MAX_BACKOFF ) {
+ nextBackoff = MAX_BACKOFF;
+ }
+ DBUtils.setLongFor( context, KEY_BACKOFF, nextBackoff );
+ }
+ setTimer( context, nextBackoff, true );
+ }
+
+ static void restartBackoff( Context context, String tag )
+ {
+ DBUtils.setLongFor( context, KEY_BACKOFF, MIN_BACKOFF );
+ setTimer( context, MIN_BACKOFF, false );
+ }
+
+ static void setTimer( Context context, boolean force )
+ {
+ long backoff = DBUtils.getLongFor( context, KEY_BACKOFF, MIN_BACKOFF );
+ setTimer( context, backoff, force );
+ }
+
+ private synchronized static void setTimer( Context context, long backoff, boolean force )
+ {
+ if ( XWPrefs.getRelayEnabled( context ) ) {
+ if ( !force ) {
+ long curBackoff = DBUtils.getLongFor( context, KEY_NEXT_BACKOFF, MIN_BACKOFF );
+ force = backoff != curBackoff;
+ }
+ if ( force ) {
+ long now = SystemClock.elapsedRealtime();
+ long fireMillis = now + backoff;
+
+ AlarmManager am =
+ (AlarmManager)context.getSystemService( Context.ALARM_SERVICE );
+
+ Intent intent = new Intent( context, RelayTimerReceiver.class );
+ PendingIntent pi = PendingIntent.getBroadcast( context, 0, intent, 0 );
+ am.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, fireMillis, pi );
+ Log.d( TAG, "setTimer() set for %d seconds from now (%d)", backoff / 1000, now / 1000 );
+ DBUtils.setLongFor( context, KEY_NEXT_BACKOFF, backoff );
+ }
+ } else {
+ Log.d( TAG, "setTimer(): relay disabled, so dropping" );
}
}
-
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
index 165e9f1ea..76db23fab 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java
@@ -148,6 +148,14 @@ public class XWPrefs {
return result;
}
+ public static boolean getRelayEnabled( Context context )
+ {
+ boolean enabled = ! getPrefsBoolean( context, R.string.key_disable_relay,
+ false );
+ // Log.d( TAG, "getRelayEnabled() => %b", enabled );
+ return enabled;
+ }
+
public static boolean getSkipToWebAPI( Context context )
{
return getPrefsBoolean( context, R.string.key_relay_via_http_first, false );
@@ -518,7 +526,7 @@ public class XWPrefs {
int flags = getPrefsInt( context, R.string.key_addrs_pref, -1 );
if ( -1 == flags ) {
result = new CommsConnTypeSet();
- if ( RelayService.relayEnabled( context ) ) {
+ if ( getRelayEnabled( context ) ) {
result.add( CommsConnType.COMMS_CONN_RELAY );
}
if ( BuildConfig.OFFER_MQTT ) {
diff --git a/xwords4/android/app/src/main/res/values/strings.xml b/xwords4/android/app/src/main/res/values/strings.xml
index bdb8946bc..f51e491b6 100644
--- a/xwords4/android/app/src/main/res/values/strings.xml
+++ b/xwords4/android/app/src/main/res/values/strings.xml
@@ -1334,12 +1334,10 @@
-
+
This action checks the relay for
- pending moves/messages for all networked games and flags those
- with pending moves. When you open a flagged game it will connect
- and sync. (In a later release these moves will be downloaded in
- the background.)
+ pending moves/messages for all networked games.
You are entering tile-exchange
mode.\n\nTap tiles to add/remove them from the set to be