@@ -235,30 +235,34 @@ private void saveRequestForLater(final Map<String, Object> args) {
235235 LeanplumEventDataManager .executeAsyncTask (new AsyncTask <Void , Void , Void >() {
236236 @ Override
237237 protected Void doInBackground (Void ... params ) {
238- synchronized (Request .class ) {
239- Context context = Leanplum .getContext ();
240- SharedPreferences preferences = context .getSharedPreferences (
241- LEANPLUM , Context .MODE_PRIVATE );
242- SharedPreferences .Editor editor = preferences .edit ();
243- long count = LeanplumEventDataManager .getEventsCount ();
244- String uuid = preferences .getString (Constants .Defaults .UUID_KEY , null );
245- if (uuid == null || count % MAX_EVENTS_PER_API_CALL == 0 ) {
246- uuid = UUID .randomUUID ().toString ();
247- editor .putString (Constants .Defaults .UUID_KEY , uuid );
248- SharedPreferencesUtil .commitChanges (editor );
249- }
250- args .put (UUID_KEY , uuid );
251- LeanplumEventDataManager .insertEvent (JsonConverter .toJson (args ));
252-
253- dataBaseIndex = count ;
254- // Checks if here response and/or error callback for this request. We need to add callbacks to
255- // eventCallbackManager only if here was internet connection, otherwise triggerErrorCallback
256- // will handle error callback for this event.
257- if (response != null || error != null && !Util .isConnected ()) {
258- eventCallbackManager .addCallbacks (currentRequest , response , error );
238+ try {
239+ synchronized (Request .class ) {
240+ Context context = Leanplum .getContext ();
241+ SharedPreferences preferences = context .getSharedPreferences (
242+ LEANPLUM , Context .MODE_PRIVATE );
243+ SharedPreferences .Editor editor = preferences .edit ();
244+ long count = LeanplumEventDataManager .getEventsCount ();
245+ String uuid = preferences .getString (Constants .Defaults .UUID_KEY , null );
246+ if (uuid == null || count % MAX_EVENTS_PER_API_CALL == 0 ) {
247+ uuid = UUID .randomUUID ().toString ();
248+ editor .putString (Constants .Defaults .UUID_KEY , uuid );
249+ SharedPreferencesUtil .commitChanges (editor );
250+ }
251+ args .put (UUID_KEY , uuid );
252+ LeanplumEventDataManager .insertEvent (JsonConverter .toJson (args ));
253+
254+ dataBaseIndex = count ;
255+ // Checks if here response and/or error callback for this request. We need to add callbacks to
256+ // eventCallbackManager only if here was internet connection, otherwise triggerErrorCallback
257+ // will handle error callback for this event.
258+ if (response != null || error != null && !Util .isConnected ()) {
259+ eventCallbackManager .addCallbacks (currentRequest , response , error );
260+ }
259261 }
260- return null ;
262+ } catch (Throwable t ) {
263+ Util .handleException (t );
261264 }
265+ return null ;
262266 }
263267 });
264268 }
@@ -333,7 +337,7 @@ private void triggerErrorCallback(Exception e) {
333337 error .error (e );
334338 }
335339 if (apiResponse != null ) {
336- List <Map <String , Object >> requests = getUnsentRequests ();
340+ List <Map <String , Object >> requests = getUnsentRequests (1.0 );
337341 List <Map <String , Object >> requestsToSend = removeIrrelevantBackgroundStartRequests (requests );
338342 apiResponse .response (requestsToSend , null , requests .size ());
339343 }
@@ -466,28 +470,98 @@ private void sendNow() {
466470 Util .executeAsyncTask (true , new AsyncTask <Void , Void , Void >() {
467471 @ Override
468472 protected Void doInBackground (Void ... params ) {
469- sendRequests ();
473+ try {
474+ sendRequests ();
475+ } catch (Throwable t ) {
476+ Util .handleException (t );
477+ }
470478 return null ;
471479 }
472480 });
473481 }
474482
475- private void sendRequests () {
483+
484+ /**
485+ * This class wraps the unsent requests, requests that we need to send
486+ * and the JSON encoded string. Wrapping it in the class allows us to
487+ * retain consistency in the requests we are sending and the actual
488+ * JSON string.
489+ */
490+ static class RequestsWithEncoding {
491+ List <Map <String , Object >> unsentRequests ;
492+ List <Map <String , Object >> requestsToSend ;
493+ String jsonEncodedString ;
494+ }
495+
496+ private RequestsWithEncoding getRequestsWithEncodedStringForErrors () {
476497 List <Map <String , Object >> unsentRequests = new ArrayList <>();
477498 List <Map <String , Object >> requestsToSend ;
499+ String jsonEncodedRequestsToSend ;
500+
501+ String uuid = UUID .randomUUID ().toString ();
502+ for (Map <String , Object > error : localErrors ) {
503+ error .put (UUID_KEY , uuid );
504+ unsentRequests .add (error );
505+ }
506+ requestsToSend = unsentRequests ;
507+ jsonEncodedRequestsToSend = jsonEncodeUnsentRequests (unsentRequests );
508+
509+ RequestsWithEncoding requestsWithEncoding = new RequestsWithEncoding ();
510+ // for errors, we send all unsent requests so they are identical
511+ requestsWithEncoding .unsentRequests = unsentRequests ;
512+ requestsWithEncoding .requestsToSend = requestsToSend ;
513+ requestsWithEncoding .jsonEncodedString = jsonEncodedRequestsToSend ;
514+
515+ return requestsWithEncoding ;
516+ }
517+
518+
519+ protected RequestsWithEncoding getRequestsWithEncodedStringStoredRequests (double fraction ) {
520+ try {
521+ List <Map <String , Object >> unsentRequests ;
522+ List <Map <String , Object >> requestsToSend ;
523+ String jsonEncodedRequestsToSend ;
524+ RequestsWithEncoding requestsWithEncoding = new RequestsWithEncoding ();
525+
526+ if (fraction < 0.01 ) { //base case
527+ unsentRequests = new ArrayList <>(0 );
528+ requestsToSend = new ArrayList <>(0 );
529+ } else {
530+ unsentRequests = getUnsentRequests (fraction );
531+ requestsToSend = removeIrrelevantBackgroundStartRequests (unsentRequests );
532+ }
533+
534+ jsonEncodedRequestsToSend = jsonEncodeUnsentRequests (unsentRequests );
535+ requestsWithEncoding .unsentRequests = unsentRequests ;
536+ requestsWithEncoding .requestsToSend = requestsToSend ;
537+ requestsWithEncoding .jsonEncodedString = jsonEncodedRequestsToSend ;
538+
539+ return requestsWithEncoding ;
540+ } catch (OutOfMemoryError E ) {
541+ // half the requests will need less memory, recursively
542+ return getRequestsWithEncodedStringStoredRequests (0.5 * fraction );
543+ }
544+ }
545+
546+ private RequestsWithEncoding getRequestsWithEncodedString () {
547+ RequestsWithEncoding requestsWithEncoding ;
478548 // Check if we have localErrors, if yes then we will send only errors to the server.
479549 if (localErrors .size () != 0 ) {
480- String uuid = UUID .randomUUID ().toString ();
481- for (Map <String , Object > error : localErrors ) {
482- error .put (UUID_KEY , uuid );
483- unsentRequests .add (error );
484- }
485- requestsToSend = unsentRequests ;
550+ requestsWithEncoding = getRequestsWithEncodedStringForErrors ();
486551 } else {
487- unsentRequests = getUnsentRequests ();
488- requestsToSend = removeIrrelevantBackgroundStartRequests (unsentRequests );
552+ requestsWithEncoding = getRequestsWithEncodedStringStoredRequests (1.0 );
489553 }
490554
555+ return requestsWithEncoding ;
556+ }
557+
558+ private void sendRequests () {
559+ RequestsWithEncoding requestsWithEncoding = getRequestsWithEncodedString ();
560+
561+ List <Map <String , Object >> unsentRequests = requestsWithEncoding .unsentRequests ;
562+ List <Map <String , Object >> requestsToSend = requestsWithEncoding .requestsToSend ;
563+ String jsonEncodedString = requestsWithEncoding .jsonEncodedString ;
564+
491565 if (requestsToSend .isEmpty ()) {
492566 return ;
493567 }
@@ -496,7 +570,7 @@ private void sendRequests() {
496570 if (!Request .attachApiKeys (multiRequestArgs )) {
497571 return ;
498572 }
499- multiRequestArgs .put (Constants .Params .DATA , jsonEncodeUnsentRequests ( requestsToSend ) );
573+ multiRequestArgs .put (Constants .Params .DATA , jsonEncodedString );
500574 multiRequestArgs .put (Constants .Params .SDK_VERSION , Constants .LEANPLUM_VERSION );
501575 multiRequestArgs .put (Constants .Params .ACTION , Constants .Methods .MULTI );
502576 multiRequestArgs .put (Constants .Params .TIME , Double .toString (new Date ().getTime () / 1000.0 ));
@@ -589,7 +663,7 @@ static void deleteSentRequests(int requestsCount) {
589663 }
590664 }
591665
592- private static List <Map <String , Object >> getUnsentRequests () {
666+ public List <Map <String , Object >> getUnsentRequests (double fraction ) {
593667 List <Map <String , Object >> requestData ;
594668
595669 synchronized (Request .class ) {
@@ -598,8 +672,8 @@ private static List<Map<String, Object>> getUnsentRequests() {
598672 SharedPreferences preferences = context .getSharedPreferences (
599673 LEANPLUM , Context .MODE_PRIVATE );
600674 SharedPreferences .Editor editor = preferences .edit ();
601-
602- requestData = LeanplumEventDataManager .getEvents (MAX_EVENTS_PER_API_CALL );
675+ int count = ( int ) ( fraction * MAX_EVENTS_PER_API_CALL );
676+ requestData = LeanplumEventDataManager .getEvents (count );
603677 editor .remove (Constants .Defaults .UUID_KEY );
604678 SharedPreferencesUtil .commitChanges (editor );
605679 }
@@ -646,7 +720,7 @@ private static List<Map<String, Object>> removeIrrelevantBackgroundStartRequests
646720 return relevantRequests ;
647721 }
648722
649- private static String jsonEncodeUnsentRequests (List <Map <String , Object >> requestData ) {
723+ protected static String jsonEncodeUnsentRequests (List <Map <String , Object >> requestData ) {
650724 Map <String , Object > data = new HashMap <>();
651725 data .put (Constants .Params .DATA , requestData );
652726 return JsonConverter .toJson (data );
0 commit comments