@@ -142,7 +142,7 @@ private static class SingletonHolder {
142142 }
143143
144144 ConnectionQueue connectionQueue_ ;
145- private final ScheduledExecutorService timerService_ ;
145+ private ScheduledExecutorService timerService_ ;
146146 private ScheduledFuture <?> timerFuture = null ;
147147 private int activityCount_ ;
148148 boolean disableUpdateSessionRequests_ = false ;//todo, move to module after 'setDisableUpdateSessionRequests' is removed
@@ -241,13 +241,8 @@ public static Countly sharedInstance() {
241241 * Creates a new ConnectionQueue and initializes the session timer.
242242 */
243243 Countly () {
244- timerService_ = Executors .newSingleThreadScheduledExecutor ();
245- staticInit ();
246- }
247-
248- private void staticInit () {
249244 connectionQueue_ = new ConnectionQueue ();
250- startTimerService ( timerService_ , timerFuture , TIMER_DELAY_IN_SECONDS );
245+ timerService_ = Executors . newSingleThreadScheduledExecutor ( );
251246 }
252247
253248 private void startTimerService (ScheduledExecutorService service , ScheduledFuture <?> previousTimer , long timerDelay ) {
@@ -260,12 +255,7 @@ private void startTimerService(ScheduledExecutorService service, ScheduledFuture
260255 timerDelay = 1 ;
261256 }
262257
263- timerFuture = service .scheduleWithFixedDelay (new Runnable () {
264- @ Override
265- public void run () {
266- onTimer ();
267- }
268- }, timerDelay , timerDelay , TimeUnit .SECONDS );
258+ timerFuture = service .scheduleWithFixedDelay (this ::onTimer , timerDelay , timerDelay , TimeUnit .SECONDS );
269259 }
270260
271261 /**
@@ -427,11 +417,13 @@ public synchronized Countly init(CountlyConfig config) {
427417 config .sdkInternalLimits .maxStackTraceLineLength = maxStackTraceLineLengthDefault ;
428418 }
429419
420+ long timerDelay = TIMER_DELAY_IN_SECONDS ;
430421 if (config .sessionUpdateTimerDelay != null ) {
431422 //if we need to change the timer delay, do that first
432423 L .d ("[Init] Setting custom session update timer delay, [" + config .sessionUpdateTimerDelay + "]" );
433- startTimerService ( timerService_ , timerFuture , config .sessionUpdateTimerDelay ) ;
424+ timerDelay = config .sessionUpdateTimerDelay ;
434425 }
426+ startTimerService (timerService_ , timerFuture , timerDelay );
435427
436428 if (config .explicitStorageModeEnabled ) {
437429 L .i ("[Init] Explicit storage mode is being enabled" );
@@ -832,17 +824,34 @@ boolean lifecycleStateAtLeastStartedInternal() {
832824 return ProcessLifecycleOwner .get ().getLifecycle ().getCurrentState ().isAtLeast (Lifecycle .State .STARTED );
833825 }
834826
827+ private void stopTimer () {
828+ L .i ("[Countly] stopTimer, Stopping global timer" );
829+ if (timerService_ != null ) {
830+ try {
831+ timerService_ .shutdown ();
832+ if (!timerService_ .awaitTermination (1 , TimeUnit .SECONDS )) {
833+ timerService_ .shutdownNow ();
834+ if (!timerService_ .awaitTermination (1 , TimeUnit .SECONDS )) {
835+ L .e ("[Countly] stopTimer, Global timer must be locked" );
836+ }
837+ }
838+ } catch (Throwable t ) {
839+ L .e ("[Countly] stopTimer, Error while stopping global timer " + t );
840+ }
841+ }
842+ }
843+
835844 /**
836- * Immediately disables session & event tracking and clears any stored session & event data.
837- * This API is useful if your app has a tracking opt-out switch, and you want to immediately
838- * disable tracking when a user opts out.
845+ * Immediately disables session and event tracking and clears any stored session and event data.
846+ * Testing Purposes Only!
839847 *
840848 * This will destroy all stored data
841849 */
842850 public synchronized void halt () {
843851 L .i ("Halting Countly!" );
844852 sdkIsInitialised = false ;
845853 L .SetListener (null );
854+ stopTimer ();
846855
847856 if (connectionQueue_ != null ) {
848857 if (countlyStore != null ) {
@@ -877,7 +886,8 @@ public synchronized void halt() {
877886 COUNTLY_SDK_VERSION_STRING = DEFAULT_COUNTLY_SDK_VERSION_STRING ;
878887 COUNTLY_SDK_NAME = DEFAULT_COUNTLY_SDK_NAME ;
879888
880- staticInit ();
889+ connectionQueue_ = new ConnectionQueue ();
890+ timerService_ = Executors .newSingleThreadScheduledExecutor ();
881891 }
882892
883893 synchronized void notifyDeviceIdChange (boolean withoutMerge ) {
0 commit comments