@@ -55,6 +55,7 @@ public class Request {
5555 private static final long DEVELOPMENT_MIN_DELAY_MS = 100 ;
5656 private static final long DEVELOPMENT_MAX_DELAY_MS = 5000 ;
5757 private static final long PRODUCTION_DELAY = 60000 ;
58+ private static final int MAX_ACTIONS_PER_API_CALL = 10000 ;
5859 private static final String LEANPLUM = "__leanplum__" ;
5960
6061 private static String appId ;
@@ -286,7 +287,7 @@ private void triggerErrorCallback(Exception e) {
286287 }
287288
288289 @ SuppressWarnings ("BooleanMethodIsAlwaysInverted" )
289- private boolean attachApiKeys (Map <String , Object > dict ) {
290+ private static boolean attachApiKeys (Map <String , Object > dict ) {
290291 if (appId == null || accessKey == null ) {
291292 Log .e ("API keys are not set. Please use Leanplum.setAppIdForDevelopmentMode or "
292293 + "Leanplum.setAppIdForProductionMode." );
@@ -378,23 +379,24 @@ private void sendNow() {
378379
379380 this .sendEventually ();
380381
381- final List <Map <String , Object >> requestsToSend = popUnsentRequests ();
382- if (requestsToSend .isEmpty ()) {
383- return ;
384- }
385-
386- final Map <String , Object > multiRequestArgs = new HashMap <>();
387- multiRequestArgs .put (Constants .Params .DATA , jsonEncodeUnsentRequests (requestsToSend ));
388- multiRequestArgs .put (Constants .Params .SDK_VERSION , Constants .LEANPLUM_VERSION );
389- multiRequestArgs .put (Constants .Params .ACTION , Constants .Methods .MULTI );
390- multiRequestArgs .put (Constants .Params .TIME , Double .toString (new Date ().getTime () / 1000.0 ));
391- if (!this .attachApiKeys (multiRequestArgs )) {
392- return ;
393- }
394-
395- Util .executeAsyncTask (new AsyncTask <Void , Void , Void >() {
382+ Util .executeAsyncTask (true , new AsyncTask <Void , Void , Void >() {
396383 @ Override
397384 protected Void doInBackground (Void ... params ) {
385+ final List <Map <String , Object >> requestsToSend = getUnsentRequests ();
386+ if (requestsToSend .isEmpty ()) {
387+ return null ;
388+ }
389+
390+ final Map <String , Object > multiRequestArgs = new HashMap <>();
391+ multiRequestArgs .put (Constants .Params .DATA , jsonEncodeUnsentRequests (requestsToSend ));
392+ multiRequestArgs .put (Constants .Params .SDK_VERSION , Constants .LEANPLUM_VERSION );
393+ multiRequestArgs .put (Constants .Params .ACTION , Constants .Methods .MULTI );
394+ multiRequestArgs .put (Constants .Params .TIME , Double .toString (new Date ().getTime () / 1000.0 ));
395+ if (!Request .attachApiKeys (multiRequestArgs )) {
396+ return null ;
397+ }
398+ saveUnsentRequest (requestsToSend );
399+
398400 JSONObject result = null ;
399401 HttpURLConnection op = null ;
400402 try {
@@ -411,11 +413,10 @@ protected Void doInBackground(Void... params) {
411413 int statusCode = op .getResponseCode ();
412414
413415 Exception errorException = null ;
414- if (statusCode >= 400 ) {
416+ if (statusCode == 200 ) {
417+ deleteSentRequests (requestsToSend .size ());
418+ } else if (statusCode >= 400 ) {
415419 errorException = new Exception ("HTTP error " + statusCode );
416- if (statusCode == 408 || (statusCode >= 500 && statusCode <= 599 )) {
417- pushUnsentRequests (requestsToSend );
418- }
419420 } else {
420421 if (result != null ) {
421422 int numResponses = Request .numResponses (result );
@@ -433,7 +434,6 @@ protected Void doInBackground(Void... params) {
433434 Log .getStackTraceString (e ));
434435 parseResponseJson (null , requestsToSend , e );
435436 } catch (Exception e ) {
436- pushUnsentRequests (requestsToSend );
437437 Log .e ("Unable to send request: " + e .toString () + "\n " +
438438 Log .getStackTraceString (e ));
439439 parseResponseJson (result , requestsToSend , e );
@@ -461,6 +461,64 @@ public void sendEventually() {
461461 }
462462 }
463463
464+ private static void deleteSentRequests (int requestSize ) {
465+ if (requestSize == 0 ) {
466+ return ;
467+ }
468+
469+ synchronized (lock ) {
470+ Context context = Leanplum .getContext ();
471+ SharedPreferences preferences = context .getSharedPreferences (
472+ LEANPLUM , Context .MODE_PRIVATE );
473+ SharedPreferences .Editor editor = preferences .edit ();
474+ int start = preferences .getInt (Constants .Defaults .START_COUNT_KEY , 0 );
475+ for (int i = start ; i < start + requestSize ; i ++) {
476+ editor .remove (String .format (Locale .US , Constants .Defaults .ITEM_KEY , i ));
477+ }
478+ editor .putInt (Constants .Defaults .START_COUNT_KEY , start + requestSize );
479+ try {
480+ editor .apply ();
481+ } catch (NoSuchMethodError e ) {
482+ editor .commit ();
483+ }
484+ }
485+ }
486+
487+ private static void updateRequest (int requestNumber , Map <String , Object > args ) {
488+ synchronized (lock ) {
489+ Context context = Leanplum .getContext ();
490+ SharedPreferences preferences = context .getSharedPreferences (
491+ LEANPLUM , Context .MODE_PRIVATE );
492+ SharedPreferences .Editor editor = preferences .edit ();
493+ int start = preferences .getInt (Constants .Defaults .START_COUNT_KEY , 0 );
494+ editor .putString (String .format (Locale .US , Constants .Defaults .ITEM_KEY , start + requestNumber ),
495+ JsonConverter .toJson (args ));
496+ try {
497+ editor .apply ();
498+ } catch (NoSuchMethodError e ) {
499+ editor .commit ();
500+ }
501+ }
502+ }
503+
504+ private static void saveUnsentRequest (List <Map <String , Object >> requestData ) {
505+ if (requestData == null || requestData .isEmpty ()) {
506+ return ;
507+ }
508+ for (int i = 0 ; i < requestData .size (); i ++) {
509+ Map <String , Object > args = requestData .get (i );
510+ Object retryCountString = args .get ("retryCount" );
511+ int retryCount ;
512+ if (retryCountString != null ) {
513+ retryCount = Integer .parseInt (retryCountString .toString ()) + 1 ;
514+ } else {
515+ retryCount = 1 ;
516+ }
517+ args .put ("retryCount" , Integer .toString (retryCount ));
518+ updateRequest (i , args );
519+ }
520+ }
521+
464522 static List <Map <String , Object >> popUnsentRequests () {
465523 return getUnsentRequests (true );
466524 }
@@ -474,7 +532,6 @@ private static List<Map<String, Object>> getUnsentRequests(boolean remove) {
474532
475533 synchronized (lock ) {
476534 lastSendTimeMs = System .currentTimeMillis ();
477-
478535 Context context = Leanplum .getContext ();
479536 SharedPreferences preferences = context .getSharedPreferences (
480537 LEANPLUM , Context .MODE_PRIVATE );
@@ -484,11 +541,11 @@ private static List<Map<String, Object>> getUnsentRequests(boolean remove) {
484541 if (count == 0 ) {
485542 return new ArrayList <>();
486543 }
487- if (remove ) {
488- editor .remove (Constants .Defaults .COUNT_KEY );
544+ int start = preferences .getInt (Constants .Defaults .START_COUNT_KEY , 0 );
545+ if (count - start > MAX_ACTIONS_PER_API_CALL ) {
546+ count = MAX_ACTIONS_PER_API_CALL ;
489547 }
490-
491- for (int i = 0 ; i < count ; i ++) {
548+ for (int i = start ; i < count ; i ++) {
492549 String itemKey = String .format (Locale .US , Constants .Defaults .ITEM_KEY , i );
493550 Map <String , Object > requestArgs ;
494551 try {
@@ -502,15 +559,16 @@ private static List<Map<String, Object>> getUnsentRequests(boolean remove) {
502559 editor .remove (itemKey );
503560 }
504561 }
505- if (remove ) {
562+ if (remove || count == start ) {
563+ editor .remove (Constants .Defaults .COUNT_KEY );
564+ editor .remove (Constants .Defaults .START_COUNT_KEY );
506565 try {
507566 editor .apply ();
508567 } catch (NoSuchMethodError e ) {
509568 editor .commit ();
510569 }
511570 }
512571 }
513-
514572 requestData = removeIrrelevantBackgroundStartRequests (requestData );
515573 return requestData ;
516574 }
@@ -560,22 +618,6 @@ private static String jsonEncodeUnsentRequests(List<Map<String, Object>> request
560618 return JsonConverter .toJson (data );
561619 }
562620
563- private static void pushUnsentRequests (List <Map <String , Object >> requestData ) {
564- if (requestData == null ) {
565- return ;
566- }
567- for (Map <String , Object > args : requestData ) {
568- Object retryCountString = args .get ("retryCount" );
569- int retryCount ;
570- if (retryCountString != null ) {
571- retryCount = Integer .parseInt (retryCountString .toString ()) + 1 ;
572- } else {
573- retryCount = 1 ;
574- }
575- args .put ("retryCount" , Integer .toString (retryCount ));
576- saveRequestForLater (args );
577- }
578- }
579621
580622 private static String getSizeAsString (int bytes ) {
581623 if (bytes < (1 << 10 )) {
@@ -650,7 +692,7 @@ public void sendFilesNow(final List<String> filenames, final List<InputStream> s
650692 printUploadProgress ();
651693
652694 // Now upload the files
653- Util .executeAsyncTask (new AsyncTask <Void , Void , Void >() {
695+ Util .executeAsyncTask (false , new AsyncTask <Void , Void , Void >() {
654696 @ Override
655697 protected Void doInBackground (Void ... params ) {
656698 synchronized (uploadFileLock ) { // Don't overload app and server with many upload tasks
@@ -734,7 +776,7 @@ void downloadFile(final String path, final String url) {
734776 return ;
735777 }
736778
737- Util .executeAsyncTask (new AsyncTask <Void , Void , Void >() {
779+ Util .executeAsyncTask (false , new AsyncTask <Void , Void , Void >() {
738780 @ Override
739781 protected Void doInBackground (Void ... params ) {
740782 try {
0 commit comments