1616package com .amazonaws .mobileconnectors .s3 .transferutility ;
1717
1818import android .content .Context ;
19+ import android .content .Intent ;
1920import android .os .Handler ;
2021import android .os .Looper ;
2122
@@ -70,6 +71,11 @@ class TransferStatusUpdater {
7071 */
7172 private final Handler mainHandler ;
7273
74+ /**
75+ * Context required to stop TransferService on all transfers completed
76+ */
77+ private Context context ;
78+
7379 /**
7480 * The Singleton instance.
7581 */
@@ -88,8 +94,9 @@ class TransferStatusUpdater {
8894 * The updater is made a singleton. Use #getInstance for getting
8995 * the object of the updater.
9096 */
91- TransferStatusUpdater (TransferDBUtil dbUtilInstance ) {
97+ TransferStatusUpdater (TransferDBUtil dbUtilInstance , Context context ) {
9298 dbUtil = dbUtilInstance ;
99+ this .context = context ;
93100 mainHandler = new Handler (Looper .getMainLooper ());
94101 transfers = new ConcurrentHashMap <Integer , TransferRecord >();
95102 }
@@ -103,7 +110,7 @@ class TransferStatusUpdater {
103110 public static synchronized TransferStatusUpdater getInstance (Context context ) {
104111 if (transferStatusUpdater == null ) {
105112 dbUtil = new TransferDBUtil (context );
106- transferStatusUpdater = new TransferStatusUpdater (dbUtil );
113+ transferStatusUpdater = new TransferStatusUpdater (dbUtil , context );
107114 }
108115 return transferStatusUpdater ;
109116 }
@@ -212,33 +219,44 @@ synchronized void updateState(final int id, final TransferState newState) {
212219
213220 synchronized (LISTENERS ) {
214221 final List <TransferListener > list = LISTENERS .get (id );
215- if (list == null || list .isEmpty ()) {
216- return ;
217- }
222+ if (list != null && !list .isEmpty ()) {
223+ // invoke TransferListener callback on main thread
224+ for (final TransferListener l : list ) {
225+ // If instance is TransferStatusListener, post immediately.
226+ // Posting to main thread can cause a missed status.
227+ if (l instanceof TransferObserver .TransferStatusListener ) {
228+ l .onStateChanged (id , newState );
229+ } else {
230+ mainHandler .post (new Runnable () {
231+ @ Override
232+ public void run () {
233+ l .onStateChanged (id , newState );
234+ }
235+ });
236+ }
237+ }
218238
219- // invoke TransferListener callback on main thread
220- for (final TransferListener l : list ) {
221- // If instance is TransferStatusListener, post immediately.
222- // Posting to main thread can cause a missed status.
223- if (l instanceof TransferObserver .TransferStatusListener ) {
224- l .onStateChanged (id , newState );
225- } else {
226- mainHandler .post (new Runnable () {
227- @ Override
228- public void run () {
229- l .onStateChanged (id , newState );
230- }
231- });
239+ // remove all LISTENERS when the transfer is in a final state so
240+ // as to release resources ASAP.
241+ if (TransferState .isFinalState (newState )) {
242+ list .clear ();
232243 }
233244 }
245+ }
234246
235- // remove all LISTENERS when the transfer is in a final state so
236- // as to release resources ASAP.
237- if (TransferState .COMPLETED .equals (newState ) ||
238- TransferState .FAILED .equals (newState ) ||
239- TransferState .CANCELED .equals (newState )) {
240- list .clear ();
247+ // If all transfers in local map are completed,
248+ // stop TransferService to clear foreground notification
249+ boolean stopTransferService = true ;
250+ for (TransferRecord record : transfers .values ()) {
251+ if (!TransferState .isFinalState (record .state )) {
252+ stopTransferService = false ;
253+ LOGGER .info ("Transfers still pending, keeping TransferService running." );
241254 }
255+ break ;
256+ }
257+ if (stopTransferService ) {
258+ LOGGER .info ("All transfers in final state. Stopping TransferService" );
259+ context .stopService (new Intent (context , TransferService .class ));
242260 }
243261 }
244262
0 commit comments