@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; }
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(); } }