@Override
  public void onReceive(Context context, Intent intent) {
    try {
      if ((null != intent) && (intent.getAction().equals("com.android.vending.INSTALL_REFERRER"))) {
        String rawReferrer = intent.getStringExtra("referrer");
        if (rawReferrer != null) {
          String referrer = URLDecoder.decode(rawReferrer, "UTF-8");
          TuneUtils.log("TUNE received referrer " + referrer);

          // Save the referrer value in SharedPreferences
          context
              .getSharedPreferences(TuneConstants.PREFS_TUNE, Context.MODE_PRIVATE)
              .edit()
              .putString(TuneConstants.KEY_REFERRER, referrer)
              .apply();

          // Notify threadpool waiting for referrer and advertising ID
          Tune tune = Tune.getInstance();
          if (tune != null) {
            tune.setInstallReferrer(referrer);
            if (tune.gotAdvertisingId && !tune.notifiedPool) {
              synchronized (tune.pool) {
                tune.pool.notifyAll();
                tune.notifiedPool = true;
              }
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * Builds JSONObject for body of POST request
   *
   * @return appropriately parameterized object
   */
  public static synchronized JSONObject buildBody(
      JSONArray eventItems, String iapData, String iapSignature, JSONArray emails) {
    JSONObject postData = new JSONObject();

    try {
      if (eventItems != null) {
        postData.put(TuneUrlKeys.EVENT_ITEMS, eventItems);
      }
      if (iapData != null) {
        postData.put(TuneUrlKeys.RECEIPT_DATA, iapData);
      }
      if (iapSignature != null) {
        postData.put(TuneUrlKeys.RECEIPT_SIGNATURE, iapSignature);
      }
      if (emails != null) {
        postData.put(TuneUrlKeys.USER_EMAILS, emails);
      }
    } catch (JSONException e) {
      TuneUtils.log("Could not build JSON body of request");
      e.printStackTrace();
    }

    return postData;
  }
  /**
   * Update the advertising ID and install referrer, if present, and encrypts the data string.
   *
   * @return encrypted string
   */
  public static synchronized String updateAndEncryptData(String data, TuneEncryption encryption) {
    if (data == null) {
      data = "";
    }

    StringBuilder updatedData = new StringBuilder(data);

    params = TuneParameters.getInstance();
    if (params != null) {
      String gaid = params.getGoogleAdvertisingId();
      if (gaid != null && !data.contains("&" + TuneUrlKeys.GOOGLE_AID + "=")) {
        safeAppend(updatedData, TuneUrlKeys.GOOGLE_AID, gaid);
        safeAppend(
            updatedData,
            TuneUrlKeys.GOOGLE_AD_TRACKING_DISABLED,
            params.getGoogleAdTrackingLimited());
      }

      String fireAid = params.getFireAdvertisingId();
      if (fireAid != null && !data.contains("&" + TuneUrlKeys.FIRE_AID + "=")) {
        safeAppend(updatedData, TuneUrlKeys.FIRE_AID, fireAid);
        safeAppend(
            updatedData, TuneUrlKeys.FIRE_AD_TRACKING_DISABLED, params.getFireAdTrackingLimited());
      }

      String androidId = params.getAndroidId();
      if (androidId != null && !data.contains("&" + TuneUrlKeys.ANDROID_ID + "=")) {
        safeAppend(updatedData, TuneUrlKeys.ANDROID_ID, androidId);
      }

      String referrer = params.getInstallReferrer();
      if (referrer != null && !data.contains("&" + TuneUrlKeys.INSTALL_REFERRER + "=")) {
        safeAppend(updatedData, TuneUrlKeys.INSTALL_REFERRER, referrer);
      }
      String referralSource = params.getReferralSource();
      if (referralSource != null && !data.contains("&" + TuneUrlKeys.REFERRAL_SOURCE + "=")) {
        safeAppend(updatedData, TuneUrlKeys.REFERRAL_SOURCE, referralSource);
      }
      String referralUrl = params.getReferralUrl();
      if (referralUrl != null && !data.contains("&" + TuneUrlKeys.REFERRAL_URL + "=")) {
        safeAppend(updatedData, TuneUrlKeys.REFERRAL_URL, referralUrl);
      }
      String userAgent = params.getUserAgent();
      if (userAgent != null && !data.contains("&" + TuneUrlKeys.USER_AGENT + "=")) {
        safeAppend(updatedData, TuneUrlKeys.USER_AGENT, userAgent);
      }
      String fbUserId = params.getFacebookUserId();
      if (fbUserId != null && !data.contains("&" + TuneUrlKeys.FACEBOOK_USER_ID + "=")) {
        safeAppend(updatedData, TuneUrlKeys.FACEBOOK_USER_ID, fbUserId);
      }
      TuneLocation location = params.getLocation();
      if (location != null) {
        if (!data.contains("&" + TuneUrlKeys.ALTITUDE + "=")) {
          safeAppend(updatedData, TuneUrlKeys.ALTITUDE, Double.toString(location.getAltitude()));
        }
        if (!data.contains("&" + TuneUrlKeys.LATITUDE + "=")) {
          safeAppend(updatedData, TuneUrlKeys.LATITUDE, Double.toString(location.getLatitude()));
        }
        if (!data.contains("&" + TuneUrlKeys.LONGITUDE + "=")) {
          safeAppend(updatedData, TuneUrlKeys.LONGITUDE, Double.toString(location.getLongitude()));
        }
      }
    }
    // Add system date of original request
    if (!data.contains("&" + TuneUrlKeys.SYSTEM_DATE + "=")) {
      long now = new Date().getTime() / 1000;
      safeAppend(updatedData, TuneUrlKeys.SYSTEM_DATE, Long.toString(now));
    }

    String updatedDataStr = updatedData.toString();
    try {
      updatedDataStr = TuneUtils.bytesToHex(encryption.encrypt(updatedDataStr));
    } catch (Exception e) {
      e.printStackTrace();
    }

    return updatedDataStr;
  }
Example #4
0
    public void run() {
      int size = getQueueSize();
      if (size == 0) return;

      try {
        queueAvailable.acquire();

        int index = 1;
        if (size > TuneConstants.MAX_DUMP_SIZE) {
          index = 1 + (size - TuneConstants.MAX_DUMP_SIZE);
        }

        // Iterate through events and do postbacks for each, using GetLink
        for (; index <= size; index++) {
          String key = Integer.toString(index);
          String eventJson = getKeyFromQueue(key);

          if (eventJson != null) {
            String link = null;
            String data = null;
            JSONObject postBody = null;
            boolean firstSession = false;
            try {
              // De-serialize the stored string from the queue to get URL and json values
              JSONObject event = new JSONObject(eventJson);
              link = event.getString("link");
              data = event.getString("data");
              postBody = event.getJSONObject("post_body");
              firstSession = event.getBoolean("first_session");
            } catch (JSONException e) {
              e.printStackTrace();
              // Can't rebuild saved request, remove from queue and return
              removeKeyFromQueue(key);
              return;
            }

            // For first session, try to wait for Google AID and install referrer before sending
            if (firstSession) {
              synchronized (tune.pool) {
                tune.pool.wait(TuneConstants.DELAY);
              }
            }

            if (tune != null) {
              boolean success = tune.makeRequest(link, data, postBody);

              if (success) {
                removeKeyFromQueue(key);
                retryTimeout = 0; // reset retry timeout after success
              } else {
                // repeat this call
                index--;
                // update retry parameter
                // maybe try a regex parse instead...
                final String paramString = "&" + TuneUrlKeys.SDK_RETRY_ATTEMPT + "=";
                int retryStart = link.indexOf(paramString);
                if (retryStart > 0) {
                  // find the longest substring that legally parses as an int
                  int attempt = -1;
                  int parseStart = retryStart + paramString.length();
                  int parseEnd = parseStart + 1;
                  while (true) {
                    String attemptString = null;
                    try {
                      attemptString = link.substring(parseStart, parseEnd);
                    } catch (StringIndexOutOfBoundsException e) {
                      break; // use last successfully parsed value
                    }
                    try {
                      attempt = Integer.parseInt(attemptString);
                      parseEnd++;
                    } catch (NumberFormatException e) {
                      break; // use last successfully parsed value
                    }
                  }
                  attempt++;
                  // 'attempt' will always be at least 0 here
                  link = link.replaceFirst(paramString + "\\d+", paramString + attempt);

                  // save updated link back to queue
                  try {
                    JSONObject event = new JSONObject(eventJson);
                    event.put("link", link);
                    setQueueItemForKey(event, key);
                  } catch (JSONException e) {
                    // error saving modified retry parameter, ignore
                    e.printStackTrace();
                  }
                }
                // choose new retry timeout, in seconds
                if (retryTimeout == 0) {
                  retryTimeout = 30;
                } else if (retryTimeout <= 30) {
                  retryTimeout = 90;
                } else if (retryTimeout <= 90) {
                  retryTimeout = 10 * 60;
                } else if (retryTimeout <= 10 * 60) {
                  retryTimeout = 60 * 60;
                } else if (retryTimeout <= 60 * 60) {
                  retryTimeout = 6 * 60 * 60;
                } else {
                  retryTimeout = 24 * 60 * 60;
                }
                // randomize and convert to milliseconds
                double timeoutMs = (1 + 0.1 * Math.random()) * retryTimeout * 1000.;
                // sleep this thread for awhile
                try {
                  Thread.sleep((long) timeoutMs);
                } catch (InterruptedException e) {
                }
              }
            } else {
              TuneUtils.log("Dropping queued request because no TUNE object was found");
              removeKeyFromQueue(key);
            }
          } else {
            // eventJson null, queued event value was lost somehow
            TuneUtils.log("Null request skipped from queue");
            removeKeyFromQueue(key);
          }
        } // for each item in queue
      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        queueAvailable.release();
      }
    }