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