mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-21 15:57:31 +09:00
pt 1 in reviving the android build (copied from pm 28a1, wish me luck)
This commit is contained in:
parent
efa9662725
commit
d7788a6d6d
4249 changed files with 468189 additions and 0 deletions
781
mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java
vendored
Normal file
781
mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java
vendored
Normal file
|
|
@ -0,0 +1,781 @@
|
|||
//
|
||||
// ActivityHandler.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.adjust.sdk.Constants.ACTIVITY_STATE_FILENAME;
|
||||
import static com.adjust.sdk.Constants.ATTRIBUTION_FILENAME;
|
||||
import static com.adjust.sdk.Constants.LOGTAG;
|
||||
|
||||
public class ActivityHandler extends HandlerThread implements IActivityHandler {
|
||||
|
||||
private static long TIMER_INTERVAL;
|
||||
private static long TIMER_START;
|
||||
private static long SESSION_INTERVAL;
|
||||
private static long SUBSESSION_INTERVAL;
|
||||
private static final String TIME_TRAVEL = "Time travel!";
|
||||
private static final String ADJUST_PREFIX = "adjust_";
|
||||
private static final String ACTIVITY_STATE_NAME = "Activity state";
|
||||
private static final String ATTRIBUTION_NAME = "Attribution";
|
||||
|
||||
private SessionHandler sessionHandler;
|
||||
private IPackageHandler packageHandler;
|
||||
private ActivityState activityState;
|
||||
private ILogger logger;
|
||||
private static ScheduledExecutorService timer;
|
||||
private boolean enabled;
|
||||
private boolean offline;
|
||||
|
||||
private DeviceInfo deviceInfo;
|
||||
private AdjustConfig adjustConfig; // always valid after construction
|
||||
private AdjustAttribution attribution;
|
||||
private IAttributionHandler attributionHandler;
|
||||
|
||||
private ActivityHandler(AdjustConfig adjustConfig) {
|
||||
super(LOGTAG, MIN_PRIORITY);
|
||||
setDaemon(true);
|
||||
start();
|
||||
|
||||
logger = AdjustFactory.getLogger();
|
||||
sessionHandler = new SessionHandler(getLooper(), this);
|
||||
enabled = true;
|
||||
init(adjustConfig);
|
||||
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.INIT;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(AdjustConfig adjustConfig) {
|
||||
this.adjustConfig = adjustConfig;
|
||||
}
|
||||
|
||||
public static ActivityHandler getInstance(AdjustConfig adjustConfig) {
|
||||
if (adjustConfig == null) {
|
||||
AdjustFactory.getLogger().error("AdjustConfig missing");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!adjustConfig.isValid()) {
|
||||
AdjustFactory.getLogger().error("AdjustConfig not initialized correctly");
|
||||
return null;
|
||||
}
|
||||
|
||||
ActivityHandler activityHandler = new ActivityHandler(adjustConfig);
|
||||
return activityHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackSubsessionStart() {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.START;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackSubsessionEnd() {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.END;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackEvent(AdjustEvent event) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.EVENT;
|
||||
message.obj = event;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishedTrackingActivity(JSONObject jsonResponse) {
|
||||
if (jsonResponse == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.FINISH_TRACKING;
|
||||
message.obj = jsonResponse;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
if (enabled == this.enabled) {
|
||||
if (enabled) {
|
||||
logger.debug("Adjust already enabled");
|
||||
} else {
|
||||
logger.debug("Adjust already disabled");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.enabled = enabled;
|
||||
if (activityState != null) {
|
||||
activityState.enabled = enabled;
|
||||
}
|
||||
if (enabled) {
|
||||
if (toPause()) {
|
||||
logger.info("Package and attribution handler remain paused due to the SDK is offline");
|
||||
} else {
|
||||
logger.info("Resuming package handler and attribution handler to enabled the SDK");
|
||||
}
|
||||
trackSubsessionStart();
|
||||
} else {
|
||||
logger.info("Pausing package handler and attribution handler to disable the SDK");
|
||||
trackSubsessionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOfflineMode(boolean offline) {
|
||||
if (offline == this.offline) {
|
||||
if (offline) {
|
||||
logger.debug("Adjust already in offline mode");
|
||||
} else {
|
||||
logger.debug("Adjust already in online mode");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.offline = offline;
|
||||
if (offline) {
|
||||
logger.info("Pausing package and attribution handler to put in offline mode");
|
||||
} else {
|
||||
if (toPause()) {
|
||||
logger.info("Package and attribution handler remain paused because the SDK is disabled");
|
||||
} else {
|
||||
logger.info("Resuming package handler and attribution handler to put in online mode");
|
||||
}
|
||||
}
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
if (activityState != null) {
|
||||
return activityState.enabled;
|
||||
} else {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOpenUrl(Uri url, long clickTime) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.DEEP_LINK;
|
||||
UrlClickTime urlClickTime = new UrlClickTime(url, clickTime);
|
||||
message.obj = urlClickTime;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryUpdateAttribution(AdjustAttribution attribution) {
|
||||
if (attribution == null) return false;
|
||||
|
||||
if (attribution.equals(this.attribution)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
saveAttribution(attribution);
|
||||
launchAttributionListener();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveAttribution(AdjustAttribution attribution) {
|
||||
this.attribution = attribution;
|
||||
writeAttribution();
|
||||
}
|
||||
|
||||
private void launchAttributionListener() {
|
||||
if (adjustConfig.onAttributionChangedListener == null) {
|
||||
return;
|
||||
}
|
||||
Handler handler = new Handler(adjustConfig.context.getMainLooper());
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adjustConfig.onAttributionChangedListener.onAttributionChanged(attribution);
|
||||
}
|
||||
};
|
||||
handler.post(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAskingAttribution(boolean askingAttribution) {
|
||||
activityState.askingAttribution = askingAttribution;
|
||||
writeActivityState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityPackage getAttributionPackage() {
|
||||
long now = System.currentTimeMillis();
|
||||
PackageBuilder attributionBuilder = new PackageBuilder(adjustConfig,
|
||||
deviceInfo,
|
||||
activityState,
|
||||
now);
|
||||
return attributionBuilder.buildAttributionPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendReferrer(String referrer, long clickTime) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.SEND_REFERRER;
|
||||
ReferrerClickTime referrerClickTime = new ReferrerClickTime(referrer, clickTime);
|
||||
message.obj = referrerClickTime;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
private class UrlClickTime {
|
||||
Uri url;
|
||||
long clickTime;
|
||||
|
||||
UrlClickTime(Uri url, long clickTime) {
|
||||
this.url = url;
|
||||
this.clickTime = clickTime;
|
||||
}
|
||||
}
|
||||
|
||||
private class ReferrerClickTime {
|
||||
String referrer;
|
||||
long clickTime;
|
||||
|
||||
ReferrerClickTime(String referrer, long clickTime) {
|
||||
this.referrer = referrer;
|
||||
this.clickTime = clickTime;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatus() {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = SessionHandler.UPDATE_STATUS;
|
||||
sessionHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
private static final class SessionHandler extends Handler {
|
||||
private static final int BASE_ADDRESS = 72630;
|
||||
private static final int INIT = BASE_ADDRESS + 1;
|
||||
private static final int START = BASE_ADDRESS + 2;
|
||||
private static final int END = BASE_ADDRESS + 3;
|
||||
private static final int EVENT = BASE_ADDRESS + 4;
|
||||
private static final int FINISH_TRACKING = BASE_ADDRESS + 5;
|
||||
private static final int DEEP_LINK = BASE_ADDRESS + 6;
|
||||
private static final int SEND_REFERRER = BASE_ADDRESS + 7;
|
||||
private static final int UPDATE_STATUS = BASE_ADDRESS + 8;
|
||||
|
||||
private final WeakReference<ActivityHandler> sessionHandlerReference;
|
||||
|
||||
protected SessionHandler(Looper looper, ActivityHandler sessionHandler) {
|
||||
super(looper);
|
||||
this.sessionHandlerReference = new WeakReference<ActivityHandler>(sessionHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
super.handleMessage(message);
|
||||
|
||||
ActivityHandler sessionHandler = sessionHandlerReference.get();
|
||||
if (sessionHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.arg1) {
|
||||
case INIT:
|
||||
sessionHandler.initInternal();
|
||||
break;
|
||||
case START:
|
||||
sessionHandler.startInternal();
|
||||
break;
|
||||
case END:
|
||||
sessionHandler.endInternal();
|
||||
break;
|
||||
case EVENT:
|
||||
AdjustEvent event = (AdjustEvent) message.obj;
|
||||
sessionHandler.trackEventInternal(event);
|
||||
break;
|
||||
case FINISH_TRACKING:
|
||||
JSONObject jsonResponse = (JSONObject) message.obj;
|
||||
sessionHandler.finishedTrackingActivityInternal(jsonResponse);
|
||||
break;
|
||||
case DEEP_LINK:
|
||||
UrlClickTime urlClickTime = (UrlClickTime) message.obj;
|
||||
sessionHandler.readOpenUrlInternal(urlClickTime.url, urlClickTime.clickTime);
|
||||
break;
|
||||
case SEND_REFERRER:
|
||||
ReferrerClickTime referrerClickTime = (ReferrerClickTime) message.obj;
|
||||
sessionHandler.sendReferrerInternal(referrerClickTime.referrer, referrerClickTime.clickTime);
|
||||
break;
|
||||
case UPDATE_STATUS:
|
||||
sessionHandler.updateStatusInternal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initInternal() {
|
||||
TIMER_INTERVAL = AdjustFactory.getTimerInterval();
|
||||
TIMER_START = AdjustFactory.getTimerStart();
|
||||
SESSION_INTERVAL = AdjustFactory.getSessionInterval();
|
||||
SUBSESSION_INTERVAL = AdjustFactory.getSubsessionInterval();
|
||||
|
||||
deviceInfo = new DeviceInfo(adjustConfig.context, adjustConfig.sdkPrefix);
|
||||
|
||||
if (adjustConfig.environment == AdjustConfig.ENVIRONMENT_PRODUCTION) {
|
||||
logger.setLogLevel(LogLevel.ASSERT);
|
||||
} else {
|
||||
logger.setLogLevel(adjustConfig.logLevel);
|
||||
}
|
||||
|
||||
if (adjustConfig.eventBufferingEnabled) {
|
||||
logger.info("Event buffering is enabled");
|
||||
}
|
||||
|
||||
String playAdId = Util.getPlayAdId(adjustConfig.context);
|
||||
if (playAdId == null) {
|
||||
logger.info("Unable to get Google Play Services Advertising ID at start time");
|
||||
}
|
||||
|
||||
if (adjustConfig.defaultTracker != null) {
|
||||
logger.info("Default tracker: '%s'", adjustConfig.defaultTracker);
|
||||
}
|
||||
|
||||
if (adjustConfig.referrer != null) {
|
||||
sendReferrer(adjustConfig.referrer, adjustConfig.referrerClickTime); // send to background queue to make sure that activityState is valid
|
||||
}
|
||||
|
||||
readAttribution();
|
||||
readActivityState();
|
||||
|
||||
packageHandler = AdjustFactory.getPackageHandler(this, adjustConfig.context, toPause());
|
||||
|
||||
startInternal();
|
||||
}
|
||||
|
||||
private void startInternal() {
|
||||
// it shouldn't start if it was disabled after a first session
|
||||
if (activityState != null
|
||||
&& !activityState.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatusInternal();
|
||||
|
||||
processSession();
|
||||
|
||||
checkAttributionState();
|
||||
|
||||
startTimer();
|
||||
}
|
||||
|
||||
private void processSession() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// very first session
|
||||
if (activityState == null) {
|
||||
activityState = new ActivityState();
|
||||
activityState.sessionCount = 1; // this is the first session
|
||||
|
||||
transferSessionPackage(now);
|
||||
activityState.resetSessionAttributes(now);
|
||||
activityState.enabled = this.enabled;
|
||||
writeActivityState();
|
||||
return;
|
||||
}
|
||||
|
||||
long lastInterval = now - activityState.lastActivity;
|
||||
|
||||
if (lastInterval < 0) {
|
||||
logger.error(TIME_TRAVEL);
|
||||
activityState.lastActivity = now;
|
||||
writeActivityState();
|
||||
return;
|
||||
}
|
||||
|
||||
// new session
|
||||
if (lastInterval > SESSION_INTERVAL) {
|
||||
activityState.sessionCount++;
|
||||
activityState.lastInterval = lastInterval;
|
||||
|
||||
transferSessionPackage(now);
|
||||
activityState.resetSessionAttributes(now);
|
||||
writeActivityState();
|
||||
return;
|
||||
}
|
||||
|
||||
// new subsession
|
||||
if (lastInterval > SUBSESSION_INTERVAL) {
|
||||
activityState.subsessionCount++;
|
||||
activityState.sessionLength += lastInterval;
|
||||
activityState.lastActivity = now;
|
||||
writeActivityState();
|
||||
logger.info("Started subsession %d of session %d",
|
||||
activityState.subsessionCount,
|
||||
activityState.sessionCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAttributionState() {
|
||||
// if there is no attribution saved, or there is one being asked
|
||||
if (attribution == null || activityState.askingAttribution) {
|
||||
getAttributionHandler().getAttribution();
|
||||
}
|
||||
}
|
||||
|
||||
private void endInternal() {
|
||||
packageHandler.pauseSending();
|
||||
getAttributionHandler().pauseSending();
|
||||
stopTimer();
|
||||
if (updateActivityState(System.currentTimeMillis())) {
|
||||
writeActivityState();
|
||||
}
|
||||
}
|
||||
|
||||
private void trackEventInternal(AdjustEvent event) {
|
||||
if (!checkEvent(event)) return;
|
||||
if (!activityState.enabled) return;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
activityState.eventCount++;
|
||||
updateActivityState(now);
|
||||
|
||||
PackageBuilder eventBuilder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
|
||||
ActivityPackage eventPackage = eventBuilder.buildEventPackage(event);
|
||||
packageHandler.addPackage(eventPackage);
|
||||
|
||||
if (adjustConfig.eventBufferingEnabled) {
|
||||
logger.info("Buffered event %s", eventPackage.getSuffix());
|
||||
} else {
|
||||
packageHandler.sendFirstPackage();
|
||||
}
|
||||
|
||||
writeActivityState();
|
||||
}
|
||||
|
||||
private void finishedTrackingActivityInternal(JSONObject jsonResponse) {
|
||||
if (jsonResponse == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String deeplink = jsonResponse.optString("deeplink", null);
|
||||
launchDeeplinkMain(deeplink);
|
||||
getAttributionHandler().checkAttribution(jsonResponse);
|
||||
}
|
||||
|
||||
private void sendReferrerInternal(String referrer, long clickTime) {
|
||||
ActivityPackage clickPackage = buildQueryStringClickPackage(referrer,
|
||||
"reftag",
|
||||
clickTime);
|
||||
if (clickPackage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAttributionHandler().getAttribution();
|
||||
|
||||
packageHandler.sendClickPackage(clickPackage);
|
||||
}
|
||||
|
||||
private void readOpenUrlInternal(Uri url, long clickTime) {
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String queryString = url.getQuery();
|
||||
|
||||
ActivityPackage clickPackage = buildQueryStringClickPackage(queryString, "deeplink", clickTime);
|
||||
if (clickPackage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAttributionHandler().getAttribution();
|
||||
|
||||
packageHandler.sendClickPackage(clickPackage);
|
||||
}
|
||||
|
||||
private ActivityPackage buildQueryStringClickPackage(String queryString, String source, long clickTime) {
|
||||
if (queryString == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, String> queryStringParameters = new HashMap<String, String>();
|
||||
AdjustAttribution queryStringAttribution = new AdjustAttribution();
|
||||
boolean hasAdjustTags = false;
|
||||
|
||||
String[] queryPairs = queryString.split("&");
|
||||
for (String pair : queryPairs) {
|
||||
if (readQueryString(pair, queryStringParameters, queryStringAttribution)) {
|
||||
hasAdjustTags = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAdjustTags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String reftag = queryStringParameters.remove("reftag");
|
||||
|
||||
PackageBuilder builder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
|
||||
builder.extraParameters = queryStringParameters;
|
||||
builder.attribution = queryStringAttribution;
|
||||
builder.reftag = reftag;
|
||||
ActivityPackage clickPackage = builder.buildClickPackage(source, clickTime);
|
||||
return clickPackage;
|
||||
}
|
||||
|
||||
private boolean readQueryString(String queryString,
|
||||
Map<String, String> extraParameters,
|
||||
AdjustAttribution queryStringAttribution) {
|
||||
String[] pairComponents = queryString.split("=");
|
||||
if (pairComponents.length != 2) return false;
|
||||
|
||||
String key = pairComponents[0];
|
||||
if (!key.startsWith(ADJUST_PREFIX)) return false;
|
||||
|
||||
String value = pairComponents[1];
|
||||
if (value.length() == 0) return false;
|
||||
|
||||
String keyWOutPrefix = key.substring(ADJUST_PREFIX.length());
|
||||
if (keyWOutPrefix.length() == 0) return false;
|
||||
|
||||
if (!trySetAttribution(queryStringAttribution, keyWOutPrefix, value)) {
|
||||
extraParameters.put(keyWOutPrefix, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean trySetAttribution(AdjustAttribution queryStringAttribution,
|
||||
String key,
|
||||
String value) {
|
||||
if (key.equals("tracker")) {
|
||||
queryStringAttribution.trackerName = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equals("campaign")) {
|
||||
queryStringAttribution.campaign = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equals("adgroup")) {
|
||||
queryStringAttribution.adgroup = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equals("creative")) {
|
||||
queryStringAttribution.creative = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateStatusInternal() {
|
||||
updateAttributionHandlerStatus();
|
||||
updatePackageHandlerStatus();
|
||||
}
|
||||
|
||||
private void updateAttributionHandlerStatus() {
|
||||
if (attributionHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (toPause()) {
|
||||
attributionHandler.pauseSending();
|
||||
} else {
|
||||
attributionHandler.resumeSending();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePackageHandlerStatus() {
|
||||
if (packageHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (toPause()) {
|
||||
packageHandler.pauseSending();
|
||||
} else {
|
||||
packageHandler.resumeSending();
|
||||
}
|
||||
}
|
||||
|
||||
private void launchDeeplinkMain(String deeplink) {
|
||||
if (deeplink == null) return;
|
||||
|
||||
Uri location = Uri.parse(deeplink);
|
||||
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
|
||||
mapIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
// Verify it resolves
|
||||
PackageManager packageManager = adjustConfig.context.getPackageManager();
|
||||
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
|
||||
boolean isIntentSafe = activities.size() > 0;
|
||||
|
||||
// Start an activity if it's safe
|
||||
if (!isIntentSafe) {
|
||||
logger.error("Unable to open deep link (%s)", deeplink);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Open deep link (%s)", deeplink);
|
||||
adjustConfig.context.startActivity(mapIntent);
|
||||
}
|
||||
|
||||
private boolean updateActivityState(long now) {
|
||||
long lastInterval = now - activityState.lastActivity;
|
||||
// ignore late updates
|
||||
if (lastInterval > SESSION_INTERVAL) {
|
||||
return false;
|
||||
}
|
||||
activityState.lastActivity = now;
|
||||
|
||||
if (lastInterval < 0) {
|
||||
logger.error(TIME_TRAVEL);
|
||||
} else {
|
||||
activityState.sessionLength += lastInterval;
|
||||
activityState.timeSpent += lastInterval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean deleteActivityState(Context context) {
|
||||
return context.deleteFile(ACTIVITY_STATE_FILENAME);
|
||||
}
|
||||
|
||||
public static boolean deleteAttribution(Context context) {
|
||||
return context.deleteFile(ATTRIBUTION_FILENAME);
|
||||
}
|
||||
|
||||
private void transferSessionPackage(long now) {
|
||||
PackageBuilder builder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
|
||||
ActivityPackage sessionPackage = builder.buildSessionPackage();
|
||||
packageHandler.addPackage(sessionPackage);
|
||||
packageHandler.sendFirstPackage();
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
stopTimer();
|
||||
|
||||
if (!activityState.enabled) {
|
||||
return;
|
||||
}
|
||||
timer = Executors.newSingleThreadScheduledExecutor();
|
||||
timer.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
timerFired();
|
||||
}
|
||||
}, TIMER_START, TIMER_INTERVAL, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
if (timer != null) {
|
||||
timer.shutdown();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void timerFired() {
|
||||
if (!activityState.enabled) {
|
||||
stopTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
packageHandler.sendFirstPackage();
|
||||
|
||||
if (updateActivityState(System.currentTimeMillis())) {
|
||||
writeActivityState();
|
||||
}
|
||||
}
|
||||
|
||||
private void readActivityState() {
|
||||
try {
|
||||
/**
|
||||
* Mozilla:
|
||||
* readObject is a generic object, and can therefore return arbitrary generic objects
|
||||
* that might not match the expected type. Therefore there will be an implicit cast
|
||||
* here, which can fail. Therefore we have to add the catch (ClassCastException)
|
||||
* Note: this has been fixed in upstream, we only need this for the version we are still shipping.
|
||||
*/
|
||||
activityState = Util.readObject(adjustConfig.context, ACTIVITY_STATE_FILENAME, ACTIVITY_STATE_NAME);
|
||||
} catch (ClassCastException e) {
|
||||
activityState = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void readAttribution() {
|
||||
try {
|
||||
/**
|
||||
* Mozilla: (same as in readActivityState() )
|
||||
* readObject is a generic object, and can therefore return arbitrary generic objects
|
||||
* that might not match the expected type. Therefore there will be an implicit cast
|
||||
* here, which can fail. Therefore we have to add the catch (ClassCastException)
|
||||
* Note: this has been fixed in upstream, we only need this for the version we are still shipping.
|
||||
*/
|
||||
attribution = Util.readObject(adjustConfig.context, ATTRIBUTION_FILENAME, ATTRIBUTION_NAME);
|
||||
} catch (ClassCastException e) {
|
||||
activityState = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeActivityState() {
|
||||
Util.writeObject(activityState, adjustConfig.context, ACTIVITY_STATE_FILENAME, ACTIVITY_STATE_NAME);
|
||||
}
|
||||
|
||||
private void writeAttribution() {
|
||||
Util.writeObject(attribution, adjustConfig.context, ATTRIBUTION_FILENAME, ATTRIBUTION_NAME);
|
||||
}
|
||||
|
||||
private boolean checkEvent(AdjustEvent event) {
|
||||
if (event == null) {
|
||||
logger.error("Event missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!event.isValid()) {
|
||||
logger.error("Event not initialized correctly");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// lazy initialization to prevent null activity state before first session
|
||||
private IAttributionHandler getAttributionHandler() {
|
||||
if (attributionHandler == null) {
|
||||
ActivityPackage attributionPackage = getAttributionPackage();
|
||||
attributionHandler = AdjustFactory.getAttributionHandler(this,
|
||||
attributionPackage,
|
||||
toPause());
|
||||
}
|
||||
return attributionHandler;
|
||||
}
|
||||
|
||||
private boolean toPause() {
|
||||
return offline || !isEnabled();
|
||||
}
|
||||
}
|
||||
35
mobile/android/thirdparty/com/adjust/sdk/ActivityKind.java
vendored
Normal file
35
mobile/android/thirdparty/com/adjust/sdk/ActivityKind.java
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
public enum ActivityKind {
|
||||
UNKNOWN, SESSION, EVENT, CLICK, ATTRIBUTION;
|
||||
|
||||
public static ActivityKind fromString(String string) {
|
||||
if ("session".equals(string)) {
|
||||
return SESSION;
|
||||
} else if ("event".equals(string)) {
|
||||
return EVENT;
|
||||
} else if ("click".equals(string)) {
|
||||
return CLICK;
|
||||
} else if ("attribution".equals(string)) {
|
||||
return ATTRIBUTION;
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case SESSION:
|
||||
return "session";
|
||||
case EVENT:
|
||||
return "event";
|
||||
case CLICK:
|
||||
return "click";
|
||||
case ATTRIBUTION:
|
||||
return "attribution";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
100
mobile/android/thirdparty/com/adjust/sdk/ActivityPackage.java
vendored
Normal file
100
mobile/android/thirdparty/com/adjust/sdk/ActivityPackage.java
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// ActivityPackage.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
public class ActivityPackage implements Serializable {
|
||||
private static final long serialVersionUID = -35935556512024097L;
|
||||
|
||||
// data
|
||||
private String path;
|
||||
private String clientSdk;
|
||||
private Map<String, String> parameters;
|
||||
|
||||
// logs
|
||||
private ActivityKind activityKind;
|
||||
private String suffix;
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getClientSdk() {
|
||||
return clientSdk;
|
||||
}
|
||||
|
||||
public void setClientSdk(String clientSdk) {
|
||||
this.clientSdk = clientSdk;
|
||||
}
|
||||
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public ActivityKind getActivityKind() {
|
||||
return activityKind;
|
||||
}
|
||||
|
||||
public void setActivityKind(ActivityKind activityKind) {
|
||||
this.activityKind = activityKind;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s%s", activityKind.toString(), suffix);
|
||||
}
|
||||
|
||||
public String getExtendedString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(String.format("Path: %s\n", path));
|
||||
builder.append(String.format("ClientSdk: %s\n", clientSdk));
|
||||
|
||||
if (parameters != null) {
|
||||
builder.append("Parameters:");
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
builder.append(String.format("\n\t%-16s %s", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
protected String getSuccessMessage() {
|
||||
try {
|
||||
return String.format("Tracked %s%s", activityKind.toString(), suffix);
|
||||
} catch (NullPointerException e) {
|
||||
return "Tracked ???";
|
||||
}
|
||||
}
|
||||
|
||||
protected String getFailureMessage() {
|
||||
try {
|
||||
return String.format("Failed to track %s%s", activityKind.toString(), suffix);
|
||||
} catch (NullPointerException e) {
|
||||
return "Failed to track ???";
|
||||
}
|
||||
}
|
||||
}
|
||||
151
mobile/android/thirdparty/com/adjust/sdk/ActivityState.java
vendored
Normal file
151
mobile/android/thirdparty/com/adjust/sdk/ActivityState.java
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
//
|
||||
// ActivityState.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectInputStream.GetField;
|
||||
import java.io.Serializable;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ActivityState implements Serializable, Cloneable {
|
||||
private static final long serialVersionUID = 9039439291143138148L;
|
||||
private transient String readErrorMessage = "Unable to read '%s' field in migration device with message (%s)";
|
||||
private transient ILogger logger;
|
||||
|
||||
// persistent data
|
||||
protected String uuid;
|
||||
protected boolean enabled;
|
||||
protected boolean askingAttribution;
|
||||
|
||||
// global counters
|
||||
protected int eventCount;
|
||||
protected int sessionCount;
|
||||
|
||||
// session attributes
|
||||
protected int subsessionCount;
|
||||
protected long sessionLength; // all durations in milliseconds
|
||||
protected long timeSpent;
|
||||
protected long lastActivity; // all times in milliseconds since 1970
|
||||
|
||||
protected long lastInterval;
|
||||
|
||||
protected ActivityState() {
|
||||
logger = AdjustFactory.getLogger();
|
||||
// create UUID for new devices
|
||||
uuid = Util.createUuid();
|
||||
enabled = true;
|
||||
askingAttribution = false;
|
||||
|
||||
eventCount = 0; // no events yet
|
||||
sessionCount = 0; // the first session just started
|
||||
subsessionCount = -1; // we don't know how many subsessions this first session will have
|
||||
sessionLength = -1; // same for session length and time spent
|
||||
timeSpent = -1; // this information will be collected and attached to the next session
|
||||
lastActivity = -1;
|
||||
lastInterval = -1;
|
||||
}
|
||||
|
||||
protected void resetSessionAttributes(long now) {
|
||||
subsessionCount = 1; // first subsession
|
||||
sessionLength = 0; // no session length yet
|
||||
timeSpent = 0; // no time spent yet
|
||||
lastActivity = now;
|
||||
lastInterval = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(Locale.US,
|
||||
"ec:%d sc:%d ssc:%d sl:%.1f ts:%.1f la:%s uuid:%s",
|
||||
eventCount, sessionCount, subsessionCount,
|
||||
sessionLength / 1000.0, timeSpent / 1000.0,
|
||||
stamp(lastActivity), uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityState clone() {
|
||||
try {
|
||||
return (ActivityState) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
|
||||
GetField fields = stream.readFields();
|
||||
|
||||
eventCount = readIntField(fields, "eventCount", 0);
|
||||
sessionCount = readIntField(fields, "sessionCount", 0);
|
||||
subsessionCount = readIntField(fields, "subsessionCount", -1);
|
||||
sessionLength = readLongField(fields, "sessionLength", -1l);
|
||||
timeSpent = readLongField(fields, "timeSpent", -1l);
|
||||
lastActivity = readLongField(fields, "lastActivity", -1l);
|
||||
lastInterval = readLongField(fields, "lastInterval", -1l);
|
||||
|
||||
// new fields
|
||||
uuid = readStringField(fields, "uuid", null);
|
||||
enabled = readBooleanField(fields, "enabled", true);
|
||||
askingAttribution = readBooleanField(fields, "askingAttribution", false);
|
||||
|
||||
// create UUID for migrating devices
|
||||
if (uuid == null) {
|
||||
uuid = Util.createUuid();
|
||||
}
|
||||
}
|
||||
|
||||
private String readStringField(GetField fields, String name, String defaultValue) {
|
||||
try {
|
||||
return (String) fields.get(name, defaultValue);
|
||||
} catch (Exception e) {
|
||||
logger.debug(readErrorMessage, name, e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean readBooleanField(GetField fields, String name, boolean defaultValue) {
|
||||
try {
|
||||
return fields.get(name, defaultValue);
|
||||
} catch (Exception e) {
|
||||
logger.debug(readErrorMessage, name, e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private int readIntField(GetField fields, String name, int defaultValue) {
|
||||
try {
|
||||
return fields.get(name, defaultValue);
|
||||
} catch (Exception e) {
|
||||
logger.debug(readErrorMessage, name, e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private long readLongField(GetField fields, String name, long defaultValue) {
|
||||
try {
|
||||
return fields.get(name, defaultValue);
|
||||
} catch (Exception e) {
|
||||
logger.debug(readErrorMessage, name, e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static String stamp(long dateMillis) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(dateMillis);
|
||||
return String.format(Locale.US,
|
||||
"%02d:%02d:%02d",
|
||||
calendar.HOUR_OF_DAY,
|
||||
calendar.MINUTE,
|
||||
calendar.SECOND);
|
||||
}
|
||||
}
|
||||
79
mobile/android/thirdparty/com/adjust/sdk/Adjust.java
vendored
Normal file
79
mobile/android/thirdparty/com/adjust/sdk/Adjust.java
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// Adjust.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2012-10-11.
|
||||
// Copyright (c) 2012-2014 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* The main interface to Adjust.
|
||||
* Use the methods of this class to tell Adjust about the usage of your app.
|
||||
* See the README for details.
|
||||
*/
|
||||
public class Adjust {
|
||||
|
||||
private static AdjustInstance defaultInstance;
|
||||
|
||||
private Adjust() {
|
||||
}
|
||||
|
||||
public static synchronized AdjustInstance getDefaultInstance() {
|
||||
if (defaultInstance == null) {
|
||||
defaultInstance = new AdjustInstance();
|
||||
}
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
public static void onCreate(AdjustConfig adjustConfig) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.onCreate(adjustConfig);
|
||||
}
|
||||
|
||||
public static void trackEvent(AdjustEvent event) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.trackEvent(event);
|
||||
}
|
||||
|
||||
public static void onResume() {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.onResume();
|
||||
}
|
||||
|
||||
public static void onPause() {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.onPause();
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean enabled) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
return adjustInstance.isEnabled();
|
||||
}
|
||||
|
||||
public static void appWillOpenUrl(Uri url) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.appWillOpenUrl(url);
|
||||
}
|
||||
|
||||
public static void setReferrer(String referrer) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.sendReferrer(referrer);
|
||||
}
|
||||
|
||||
public static void setOfflineMode(boolean enabled) {
|
||||
AdjustInstance adjustInstance = Adjust.getDefaultInstance();
|
||||
adjustInstance.setOfflineMode(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
62
mobile/android/thirdparty/com/adjust/sdk/AdjustAttribution.java
vendored
Normal file
62
mobile/android/thirdparty/com/adjust/sdk/AdjustAttribution.java
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by pfms on 07/11/14.
|
||||
*/
|
||||
public class AdjustAttribution implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public String trackerToken;
|
||||
public String trackerName;
|
||||
public String network;
|
||||
public String campaign;
|
||||
public String adgroup;
|
||||
public String creative;
|
||||
|
||||
public static AdjustAttribution fromJson(JSONObject jsonObject) {
|
||||
if (jsonObject == null) return null;
|
||||
|
||||
AdjustAttribution attribution = new AdjustAttribution();
|
||||
|
||||
attribution.trackerToken = jsonObject.optString("tracker_token", null);
|
||||
attribution.trackerName = jsonObject.optString("tracker_name", null);
|
||||
attribution.network = jsonObject.optString("network", null);
|
||||
attribution.campaign = jsonObject.optString("campaign", null);
|
||||
attribution.adgroup = jsonObject.optString("adgroup", null);
|
||||
attribution.creative = jsonObject.optString("creative", null);
|
||||
|
||||
return attribution;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) return true;
|
||||
if (other == null) return false;
|
||||
if (getClass() != other.getClass()) return false;
|
||||
AdjustAttribution otherAttribution = (AdjustAttribution) other;
|
||||
|
||||
if (!equalString(trackerToken, otherAttribution.trackerToken)) return false;
|
||||
if (!equalString(trackerName, otherAttribution.trackerName)) return false;
|
||||
if (!equalString(network, otherAttribution.network)) return false;
|
||||
if (!equalString(campaign, otherAttribution.campaign)) return false;
|
||||
if (!equalString(adgroup, otherAttribution.adgroup)) return false;
|
||||
if (!equalString(creative, otherAttribution.creative)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean equalString(String first, String second) {
|
||||
if (first == null || second == null) {
|
||||
return first == null && second == null;
|
||||
}
|
||||
return first.equals(second);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("tt:%s tn:%s net:%s cam:%s adg:%s cre:%s",
|
||||
trackerToken, trackerName, network, campaign, adgroup, creative);
|
||||
}
|
||||
}
|
||||
128
mobile/android/thirdparty/com/adjust/sdk/AdjustConfig.java
vendored
Normal file
128
mobile/android/thirdparty/com/adjust/sdk/AdjustConfig.java
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Created by pfms on 06/11/14.
|
||||
*/
|
||||
public class AdjustConfig {
|
||||
Context context;
|
||||
String appToken;
|
||||
String environment;
|
||||
LogLevel logLevel;
|
||||
String sdkPrefix;
|
||||
Boolean eventBufferingEnabled;
|
||||
String defaultTracker;
|
||||
OnAttributionChangedListener onAttributionChangedListener;
|
||||
String referrer;
|
||||
long referrerClickTime;
|
||||
Boolean knownDevice;
|
||||
|
||||
public static final String ENVIRONMENT_SANDBOX = "sandbox";
|
||||
public static final String ENVIRONMENT_PRODUCTION = "production";
|
||||
|
||||
public AdjustConfig(Context context, String appToken, String environment) {
|
||||
if (!isValid(context, appToken, environment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.context = context.getApplicationContext();
|
||||
this.appToken = appToken;
|
||||
this.environment = environment;
|
||||
|
||||
// default values
|
||||
this.logLevel = LogLevel.INFO;
|
||||
this.eventBufferingEnabled = false;
|
||||
}
|
||||
|
||||
public void setEventBufferingEnabled(Boolean eventBufferingEnabled) {
|
||||
this.eventBufferingEnabled = eventBufferingEnabled;
|
||||
}
|
||||
|
||||
public void setLogLevel(LogLevel logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
public void setSdkPrefix(String sdkPrefix) {
|
||||
this.sdkPrefix = sdkPrefix;
|
||||
}
|
||||
|
||||
public void setDefaultTracker(String defaultTracker) {
|
||||
this.defaultTracker = defaultTracker;
|
||||
}
|
||||
|
||||
public void setOnAttributionChangedListener(OnAttributionChangedListener onAttributionChangedListener) {
|
||||
this.onAttributionChangedListener = onAttributionChangedListener;
|
||||
}
|
||||
|
||||
public boolean hasListener() {
|
||||
return onAttributionChangedListener != null;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return appToken != null;
|
||||
}
|
||||
|
||||
private boolean isValid(Context context, String appToken, String environment) {
|
||||
if (!checkAppToken(appToken)) return false;
|
||||
if (!checkEnvironment(environment)) return false;
|
||||
if (!checkContext(context)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkContext(Context context) {
|
||||
ILogger logger = AdjustFactory.getLogger();
|
||||
if (context == null) {
|
||||
logger.error("Missing context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Util.checkPermission(context, android.Manifest.permission.INTERNET)) {
|
||||
logger.error("Missing permission: INTERNET");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkAppToken(String appToken) {
|
||||
ILogger logger = AdjustFactory.getLogger();
|
||||
if (appToken == null) {
|
||||
logger.error("Missing App Token.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (appToken.length() != 12) {
|
||||
logger.error("Malformed App Token '%s'", appToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkEnvironment(String environment) {
|
||||
ILogger logger = AdjustFactory.getLogger();
|
||||
if (environment == null) {
|
||||
logger.error("Missing environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (environment == AdjustConfig.ENVIRONMENT_SANDBOX) {
|
||||
logger.Assert("SANDBOX: Adjust is running in Sandbox mode. " +
|
||||
"Use this setting for testing. " +
|
||||
"Don't forget to set the environment to `production` before publishing!");
|
||||
return true;
|
||||
}
|
||||
if (environment == AdjustConfig.ENVIRONMENT_PRODUCTION) {
|
||||
logger.Assert(
|
||||
"PRODUCTION: Adjust is running in Production mode. " +
|
||||
"Use this setting only for the build that you want to publish. " +
|
||||
"Set the environment to `sandbox` if you want to test your app!");
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.error("Unknown environment '%s'", environment);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
112
mobile/android/thirdparty/com/adjust/sdk/AdjustEvent.java
vendored
Normal file
112
mobile/android/thirdparty/com/adjust/sdk/AdjustEvent.java
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by pfms on 05/11/14.
|
||||
*/
|
||||
public class AdjustEvent {
|
||||
String eventToken;
|
||||
Double revenue;
|
||||
String currency;
|
||||
Map<String, String> callbackParameters;
|
||||
Map<String, String> partnerParameters;
|
||||
|
||||
private static ILogger logger = AdjustFactory.getLogger();
|
||||
|
||||
public AdjustEvent(String eventToken) {
|
||||
if (!checkEventToken(eventToken, logger)) return;
|
||||
|
||||
this.eventToken = eventToken;
|
||||
}
|
||||
|
||||
public void setRevenue(double revenue, String currency) {
|
||||
if (!checkRevenue(revenue, currency)) return;
|
||||
|
||||
this.revenue = revenue;
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public void addCallbackParameter(String key, String value) {
|
||||
if (!isValidParameter(key, "key", "Callback")) return;
|
||||
if (!isValidParameter(value, "value", "Callback")) return;
|
||||
|
||||
if (callbackParameters == null) {
|
||||
callbackParameters = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
String previousValue = callbackParameters.put(key, value);
|
||||
|
||||
if (previousValue != null) {
|
||||
logger.warn("key %s was overwritten", key);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPartnerParameter(String key, String value) {
|
||||
if (!isValidParameter(key, "key", "Partner")) return;
|
||||
if (!isValidParameter(value, "value", "Partner")) return;
|
||||
|
||||
if (partnerParameters == null) {
|
||||
partnerParameters = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
String previousValue = partnerParameters.put(key, value);
|
||||
|
||||
if (previousValue != null) {
|
||||
logger.warn("key %s was overwritten", key);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return eventToken != null;
|
||||
}
|
||||
|
||||
private static boolean checkEventToken(String eventToken, ILogger logger) {
|
||||
if (eventToken == null) {
|
||||
logger.error("Missing Event Token");
|
||||
return false;
|
||||
}
|
||||
if (eventToken.length() != 6) {
|
||||
logger.error("Malformed Event Token '%s'", eventToken);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkRevenue(Double revenue, String currency) {
|
||||
if (revenue != null) {
|
||||
if (revenue < 0.0) {
|
||||
logger.error("Invalid amount %.4f", revenue);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currency == null) {
|
||||
logger.error("Currency must be set with revenue");
|
||||
return false;
|
||||
}
|
||||
if (currency == "") {
|
||||
logger.error("Currency is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (currency != null) {
|
||||
logger.error("Revenue must be set with currency");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidParameter(String attribute, String attributeType, String parameterName) {
|
||||
if (attribute == null) {
|
||||
logger.error("%s parameter %s is missing", parameterName, attributeType);
|
||||
return false;
|
||||
}
|
||||
if (attribute == "") {
|
||||
logger.error("%s parameter %s is empty", parameterName, attributeType);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
141
mobile/android/thirdparty/com/adjust/sdk/AdjustFactory.java
vendored
Normal file
141
mobile/android/thirdparty/com/adjust/sdk/AdjustFactory.java
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import ch.boye.httpclientandroidlib.client.HttpClient;
|
||||
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
|
||||
import ch.boye.httpclientandroidlib.params.HttpParams;
|
||||
|
||||
public class AdjustFactory {
|
||||
private static IPackageHandler packageHandler = null;
|
||||
private static IRequestHandler requestHandler = null;
|
||||
private static IAttributionHandler attributionHandler = null;
|
||||
private static IActivityHandler activityHandler = null;
|
||||
private static ILogger logger = null;
|
||||
private static HttpClient httpClient = null;
|
||||
|
||||
private static long timerInterval = -1;
|
||||
private static long timerStart = -1;
|
||||
private static long sessionInterval = -1;
|
||||
private static long subsessionInterval = -1;
|
||||
|
||||
public static IPackageHandler getPackageHandler(ActivityHandler activityHandler,
|
||||
Context context,
|
||||
boolean startPaused) {
|
||||
if (packageHandler == null) {
|
||||
return new PackageHandler(activityHandler, context, startPaused);
|
||||
}
|
||||
packageHandler.init(activityHandler, context, startPaused);
|
||||
return packageHandler;
|
||||
}
|
||||
|
||||
public static IRequestHandler getRequestHandler(IPackageHandler packageHandler) {
|
||||
if (requestHandler == null) {
|
||||
return new RequestHandler(packageHandler);
|
||||
}
|
||||
requestHandler.init(packageHandler);
|
||||
return requestHandler;
|
||||
}
|
||||
|
||||
public static ILogger getLogger() {
|
||||
if (logger == null) {
|
||||
// Logger needs to be "static" to retain the configuration throughout the app
|
||||
logger = new Logger();
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
public static HttpClient getHttpClient(HttpParams params) {
|
||||
if (httpClient == null) {
|
||||
return new DefaultHttpClient(params);
|
||||
}
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public static long getTimerInterval() {
|
||||
if (timerInterval == -1) {
|
||||
return Constants.ONE_MINUTE;
|
||||
}
|
||||
return timerInterval;
|
||||
}
|
||||
|
||||
public static long getTimerStart() {
|
||||
if (timerStart == -1) {
|
||||
return 0;
|
||||
}
|
||||
return timerStart;
|
||||
}
|
||||
|
||||
public static long getSessionInterval() {
|
||||
if (sessionInterval == -1) {
|
||||
return Constants.THIRTY_MINUTES;
|
||||
}
|
||||
return sessionInterval;
|
||||
}
|
||||
|
||||
public static long getSubsessionInterval() {
|
||||
if (subsessionInterval == -1) {
|
||||
return Constants.ONE_SECOND;
|
||||
}
|
||||
return subsessionInterval;
|
||||
}
|
||||
|
||||
public static IActivityHandler getActivityHandler(AdjustConfig config) {
|
||||
if (activityHandler == null) {
|
||||
return ActivityHandler.getInstance(config);
|
||||
}
|
||||
activityHandler.init(config);
|
||||
return activityHandler;
|
||||
}
|
||||
|
||||
public static IAttributionHandler getAttributionHandler(IActivityHandler activityHandler,
|
||||
ActivityPackage attributionPackage,
|
||||
boolean startPaused) {
|
||||
if (attributionHandler == null) {
|
||||
return new AttributionHandler(activityHandler, attributionPackage, startPaused);
|
||||
}
|
||||
attributionHandler.init(activityHandler, attributionPackage, startPaused);
|
||||
return attributionHandler;
|
||||
}
|
||||
|
||||
public static void setPackageHandler(IPackageHandler packageHandler) {
|
||||
AdjustFactory.packageHandler = packageHandler;
|
||||
}
|
||||
|
||||
public static void setRequestHandler(IRequestHandler requestHandler) {
|
||||
AdjustFactory.requestHandler = requestHandler;
|
||||
}
|
||||
|
||||
public static void setLogger(ILogger logger) {
|
||||
AdjustFactory.logger = logger;
|
||||
}
|
||||
|
||||
public static void setHttpClient(HttpClient httpClient) {
|
||||
AdjustFactory.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public static void setTimerInterval(long timerInterval) {
|
||||
AdjustFactory.timerInterval = timerInterval;
|
||||
}
|
||||
|
||||
public static void setTimerStart(long timerStart) {
|
||||
AdjustFactory.timerStart = timerStart;
|
||||
}
|
||||
|
||||
public static void setSessionInterval(long sessionInterval) {
|
||||
AdjustFactory.sessionInterval = sessionInterval;
|
||||
}
|
||||
|
||||
public static void setSubsessionInterval(long subsessionInterval) {
|
||||
AdjustFactory.subsessionInterval = subsessionInterval;
|
||||
}
|
||||
|
||||
public static void setActivityHandler(IActivityHandler activityHandler) {
|
||||
AdjustFactory.activityHandler = activityHandler;
|
||||
}
|
||||
|
||||
public static void setAttributionHandler(IAttributionHandler attributionHandler) {
|
||||
AdjustFactory.attributionHandler = attributionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
86
mobile/android/thirdparty/com/adjust/sdk/AdjustInstance.java
vendored
Normal file
86
mobile/android/thirdparty/com/adjust/sdk/AdjustInstance.java
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* Created by pfms on 04/12/14.
|
||||
*/
|
||||
public class AdjustInstance {
|
||||
|
||||
private String referrer;
|
||||
private long referrerClickTime;
|
||||
private ActivityHandler activityHandler;
|
||||
|
||||
private static ILogger getLogger() {
|
||||
return AdjustFactory.getLogger();
|
||||
}
|
||||
|
||||
public void onCreate(AdjustConfig adjustConfig) {
|
||||
if (activityHandler != null) {
|
||||
getLogger().error("Adjust already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
adjustConfig.referrer = this.referrer;
|
||||
adjustConfig.referrerClickTime = this.referrerClickTime;
|
||||
|
||||
activityHandler = ActivityHandler.getInstance(adjustConfig);
|
||||
}
|
||||
|
||||
public void trackEvent(AdjustEvent event) {
|
||||
if (!checkActivityHandler()) return;
|
||||
activityHandler.trackEvent(event);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
if (!checkActivityHandler()) return;
|
||||
activityHandler.trackSubsessionStart();
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if (!checkActivityHandler()) return;
|
||||
activityHandler.trackSubsessionEnd();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
if (!checkActivityHandler()) return;
|
||||
activityHandler.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
if (!checkActivityHandler()) return false;
|
||||
return activityHandler.isEnabled();
|
||||
}
|
||||
|
||||
public void appWillOpenUrl(Uri url) {
|
||||
if (!checkActivityHandler()) return;
|
||||
long clickTime = System.currentTimeMillis();
|
||||
activityHandler.readOpenUrl(url, clickTime);
|
||||
}
|
||||
|
||||
public void sendReferrer(String referrer) {
|
||||
long clickTime = System.currentTimeMillis();
|
||||
// sendReferrer might be triggered before Adjust
|
||||
if (activityHandler == null) {
|
||||
// save it to inject in the config before launch
|
||||
this.referrer = referrer;
|
||||
this.referrerClickTime = clickTime;
|
||||
} else {
|
||||
activityHandler.sendReferrer(referrer, clickTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOfflineMode(boolean enabled) {
|
||||
if (!checkActivityHandler()) return;
|
||||
activityHandler.setOfflineMode(enabled);
|
||||
}
|
||||
|
||||
private boolean checkActivityHandler() {
|
||||
if (activityHandler == null) {
|
||||
getLogger().error("Please initialize Adjust by calling 'onCreate' before");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
mobile/android/thirdparty/com/adjust/sdk/AdjustReferrerReceiver.java
vendored
Normal file
35
mobile/android/thirdparty/com/adjust/sdk/AdjustReferrerReceiver.java
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import static com.adjust.sdk.Constants.ENCODING;
|
||||
import static com.adjust.sdk.Constants.MALFORMED;
|
||||
import static com.adjust.sdk.Constants.REFERRER;
|
||||
|
||||
// support multiple BroadcastReceivers for the INSTALL_REFERRER:
|
||||
// http://blog.appington.com/2012/08/01/giving-credit-for-android-app-installs
|
||||
|
||||
public class AdjustReferrerReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String rawReferrer = intent.getStringExtra(REFERRER);
|
||||
if (null == rawReferrer) {
|
||||
return;
|
||||
}
|
||||
|
||||
String referrer;
|
||||
try {
|
||||
referrer = URLDecoder.decode(rawReferrer, ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
referrer = MALFORMED;
|
||||
}
|
||||
|
||||
AdjustInstance adjust = Adjust.getDefaultInstance();
|
||||
adjust.sendReferrer(referrer);
|
||||
}
|
||||
}
|
||||
155
mobile/android/thirdparty/com/adjust/sdk/AttributionHandler.java
vendored
Normal file
155
mobile/android/thirdparty/com/adjust/sdk/AttributionHandler.java
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||
import ch.boye.httpclientandroidlib.client.HttpClient;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpGet;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by pfms on 07/11/14.
|
||||
*/
|
||||
public class AttributionHandler implements IAttributionHandler {
|
||||
private ScheduledExecutorService scheduler;
|
||||
private IActivityHandler activityHandler;
|
||||
private ILogger logger;
|
||||
private ActivityPackage attributionPackage;
|
||||
private ScheduledFuture waitingTask;
|
||||
private HttpClient httpClient;
|
||||
private boolean paused;
|
||||
|
||||
public AttributionHandler(IActivityHandler activityHandler,
|
||||
ActivityPackage attributionPackage,
|
||||
boolean startPaused) {
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||
logger = AdjustFactory.getLogger();
|
||||
httpClient = Util.getHttpClient();
|
||||
init(activityHandler, attributionPackage, startPaused);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IActivityHandler activityHandler,
|
||||
ActivityPackage attributionPackage,
|
||||
boolean startPaused) {
|
||||
this.activityHandler = activityHandler;
|
||||
this.attributionPackage = attributionPackage;
|
||||
this.paused = startPaused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAttribution() {
|
||||
getAttribution(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAttribution(final JSONObject jsonResponse) {
|
||||
scheduler.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
checkAttributionInternal(jsonResponse);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseSending() {
|
||||
paused = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeSending() {
|
||||
paused = false;
|
||||
}
|
||||
|
||||
private void getAttribution(int delayInMilliseconds) {
|
||||
if (waitingTask != null) {
|
||||
waitingTask.cancel(false);
|
||||
}
|
||||
|
||||
if (delayInMilliseconds != 0) {
|
||||
logger.debug("Waiting to query attribution in %d milliseconds", delayInMilliseconds);
|
||||
}
|
||||
|
||||
waitingTask = scheduler.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getAttributionInternal();
|
||||
}
|
||||
}, delayInMilliseconds, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void checkAttributionInternal(JSONObject jsonResponse) {
|
||||
if (jsonResponse == null) return;
|
||||
|
||||
JSONObject attributionJson = jsonResponse.optJSONObject("attribution");
|
||||
AdjustAttribution attribution = AdjustAttribution.fromJson(attributionJson);
|
||||
|
||||
int timerMilliseconds = jsonResponse.optInt("ask_in", -1);
|
||||
|
||||
// without ask_in attribute
|
||||
if (timerMilliseconds < 0) {
|
||||
activityHandler.tryUpdateAttribution(attribution);
|
||||
|
||||
activityHandler.setAskingAttribution(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
activityHandler.setAskingAttribution(true);
|
||||
|
||||
getAttribution(timerMilliseconds);
|
||||
}
|
||||
|
||||
private void getAttributionInternal() {
|
||||
if (paused) {
|
||||
logger.debug("Attribution Handler is paused");
|
||||
return;
|
||||
}
|
||||
logger.verbose("%s", attributionPackage.getExtendedString());
|
||||
HttpResponse httpResponse = null;
|
||||
try {
|
||||
HttpGet request = getRequest(attributionPackage);
|
||||
httpResponse = httpClient.execute(request);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get attribution (%s)", e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject jsonResponse = Util.parseJsonResponse(httpResponse, logger);
|
||||
|
||||
checkAttributionInternal(jsonResponse);
|
||||
}
|
||||
|
||||
private Uri buildUri(ActivityPackage attributionPackage) {
|
||||
Uri.Builder uriBuilder = new Uri.Builder();
|
||||
|
||||
uriBuilder.scheme(Constants.SCHEME);
|
||||
uriBuilder.authority(Constants.AUTHORITY);
|
||||
uriBuilder.appendPath(attributionPackage.getPath());
|
||||
|
||||
for (Map.Entry<String, String> entry : attributionPackage.getParameters().entrySet()) {
|
||||
uriBuilder.appendQueryParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return uriBuilder.build();
|
||||
}
|
||||
|
||||
private HttpGet getRequest(ActivityPackage attributionPackage) throws URISyntaxException {
|
||||
HttpGet request = new HttpGet();
|
||||
Uri uri = buildUri(attributionPackage);
|
||||
request.setURI(new URI(uri.toString()));
|
||||
|
||||
request.addHeader("Client-SDK", attributionPackage.getClientSdk());
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
53
mobile/android/thirdparty/com/adjust/sdk/Constants.java
vendored
Normal file
53
mobile/android/thirdparty/com/adjust/sdk/Constants.java
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// Constants.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by keyboardsurfer on 2013-11-08.
|
||||
// Copyright (c) 2012-2014 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author keyboardsurfer
|
||||
* @since 8.11.13
|
||||
*/
|
||||
public interface Constants {
|
||||
int ONE_SECOND = 1000;
|
||||
int ONE_MINUTE = 60 * ONE_SECOND;
|
||||
int THIRTY_MINUTES = 30 * ONE_MINUTE;
|
||||
|
||||
int CONNECTION_TIMEOUT = Constants.ONE_MINUTE;
|
||||
int SOCKET_TIMEOUT = Constants.ONE_MINUTE;
|
||||
|
||||
String BASE_URL = "https://app.adjust.com";
|
||||
String SCHEME = "https";
|
||||
String AUTHORITY = "app.adjust.com";
|
||||
String CLIENT_SDK = "android4.0.0";
|
||||
String LOGTAG = "Adjust";
|
||||
|
||||
String ACTIVITY_STATE_FILENAME = "AdjustIoActivityState";
|
||||
String ATTRIBUTION_FILENAME = "AdjustAttribution";
|
||||
|
||||
String MALFORMED = "malformed";
|
||||
String SMALL = "small";
|
||||
String NORMAL = "normal";
|
||||
String LONG = "long";
|
||||
String LARGE = "large";
|
||||
String XLARGE = "xlarge";
|
||||
String LOW = "low";
|
||||
String MEDIUM = "medium";
|
||||
String HIGH = "high";
|
||||
String REFERRER = "referrer";
|
||||
|
||||
String ENCODING = "UTF-8";
|
||||
String MD5 = "MD5";
|
||||
String SHA1 = "SHA-1";
|
||||
|
||||
// List of known plugins, possibly not active
|
||||
List<String> PLUGINS = Arrays.asList();
|
||||
}
|
||||
290
mobile/android/thirdparty/com/adjust/sdk/DeviceInfo.java
vendored
Normal file
290
mobile/android/thirdparty/com/adjust/sdk/DeviceInfo.java
vendored
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.adjust.sdk.Constants.ENCODING;
|
||||
import static com.adjust.sdk.Constants.HIGH;
|
||||
import static com.adjust.sdk.Constants.LARGE;
|
||||
import static com.adjust.sdk.Constants.LONG;
|
||||
import static com.adjust.sdk.Constants.LOW;
|
||||
import static com.adjust.sdk.Constants.MD5;
|
||||
import static com.adjust.sdk.Constants.MEDIUM;
|
||||
import static com.adjust.sdk.Constants.NORMAL;
|
||||
import static com.adjust.sdk.Constants.SHA1;
|
||||
import static com.adjust.sdk.Constants.SMALL;
|
||||
import static com.adjust.sdk.Constants.XLARGE;
|
||||
|
||||
/**
|
||||
* Created by pfms on 06/11/14.
|
||||
*/
|
||||
class DeviceInfo {
|
||||
String macSha1;
|
||||
String macShortMd5;
|
||||
String androidId;
|
||||
String fbAttributionId;
|
||||
String clientSdk;
|
||||
String packageName;
|
||||
String appVersion;
|
||||
String deviceType;
|
||||
String deviceName;
|
||||
String deviceManufacturer;
|
||||
String osName;
|
||||
String osVersion;
|
||||
String language;
|
||||
String country;
|
||||
String screenSize;
|
||||
String screenFormat;
|
||||
String screenDensity;
|
||||
String displayWidth;
|
||||
String displayHeight;
|
||||
Map<String, String> pluginKeys;
|
||||
|
||||
DeviceInfo(Context context, String sdkPrefix) {
|
||||
Resources resources = context.getResources();
|
||||
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
||||
Configuration configuration = resources.getConfiguration();
|
||||
Locale locale = configuration.locale;
|
||||
int screenLayout = configuration.screenLayout;
|
||||
boolean isGooglePlayServicesAvailable = Reflection.isGooglePlayServicesAvailable(context);
|
||||
String macAddress = getMacAddress(context, isGooglePlayServicesAvailable);
|
||||
|
||||
packageName = getPackageName(context);
|
||||
appVersion = getAppVersion(context);
|
||||
deviceType = getDeviceType(screenLayout);
|
||||
deviceName = getDeviceName();
|
||||
deviceManufacturer = getDeviceManufacturer();
|
||||
osName = getOsName();
|
||||
osVersion = getOsVersion();
|
||||
language = getLanguage(locale);
|
||||
country = getCountry(locale);
|
||||
screenSize = getScreenSize(screenLayout);
|
||||
screenFormat = getScreenFormat(screenLayout);
|
||||
screenDensity = getScreenDensity(displayMetrics);
|
||||
displayWidth = getDisplayWidth(displayMetrics);
|
||||
displayHeight = getDisplayHeight(displayMetrics);
|
||||
clientSdk = getClientSdk(sdkPrefix);
|
||||
androidId = getAndroidId(context, isGooglePlayServicesAvailable);
|
||||
fbAttributionId = getFacebookAttributionId(context);
|
||||
pluginKeys = Reflection.getPluginKeys(context);
|
||||
macSha1 = getMacSha1(macAddress);
|
||||
macShortMd5 = getMacShortMd5(macAddress);
|
||||
}
|
||||
|
||||
private String getMacAddress(Context context, boolean isGooglePlayServicesAvailable) {
|
||||
if (!isGooglePlayServicesAvailable) {
|
||||
if (!!Util.checkPermission(context, android.Manifest.permission.ACCESS_WIFI_STATE)) {
|
||||
AdjustFactory.getLogger().warn("Missing permission: ACCESS_WIFI_STATE");
|
||||
}
|
||||
return Reflection.getMacAddress(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getPackageName(Context context) {
|
||||
return context.getPackageName();
|
||||
}
|
||||
|
||||
private String getAppVersion(Context context) {
|
||||
try {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
String name = context.getPackageName();
|
||||
PackageInfo info = packageManager.getPackageInfo(name, 0);
|
||||
return info.versionName;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getDeviceType(int screenLayout) {
|
||||
int screenSize = screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
|
||||
|
||||
switch (screenSize) {
|
||||
case Configuration.SCREENLAYOUT_SIZE_SMALL:
|
||||
case Configuration.SCREENLAYOUT_SIZE_NORMAL:
|
||||
return "phone";
|
||||
case Configuration.SCREENLAYOUT_SIZE_LARGE:
|
||||
case 4:
|
||||
return "tablet";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getDeviceName() {
|
||||
return Build.MODEL;
|
||||
}
|
||||
|
||||
private String getDeviceManufacturer() {
|
||||
return Build.MANUFACTURER;
|
||||
}
|
||||
|
||||
private String getOsName() {
|
||||
return "android";
|
||||
}
|
||||
|
||||
private String getOsVersion() {
|
||||
return osVersion = "" + Build.VERSION.SDK_INT;
|
||||
}
|
||||
|
||||
private String getLanguage(Locale locale) {
|
||||
return locale.getLanguage();
|
||||
}
|
||||
|
||||
private String getCountry(Locale locale) {
|
||||
return locale.getCountry();
|
||||
}
|
||||
|
||||
private String getScreenSize(int screenLayout) {
|
||||
int screenSize = screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
|
||||
|
||||
switch (screenSize) {
|
||||
case Configuration.SCREENLAYOUT_SIZE_SMALL:
|
||||
return SMALL;
|
||||
case Configuration.SCREENLAYOUT_SIZE_NORMAL:
|
||||
return NORMAL;
|
||||
case Configuration.SCREENLAYOUT_SIZE_LARGE:
|
||||
return LARGE;
|
||||
case 4:
|
||||
return XLARGE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getScreenFormat(int screenLayout) {
|
||||
int screenFormat = screenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
|
||||
|
||||
switch (screenFormat) {
|
||||
case Configuration.SCREENLAYOUT_LONG_YES:
|
||||
return LONG;
|
||||
case Configuration.SCREENLAYOUT_LONG_NO:
|
||||
return NORMAL;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getScreenDensity(DisplayMetrics displayMetrics) {
|
||||
int density = displayMetrics.densityDpi;
|
||||
int low = (DisplayMetrics.DENSITY_MEDIUM + DisplayMetrics.DENSITY_LOW) / 2;
|
||||
int high = (DisplayMetrics.DENSITY_MEDIUM + DisplayMetrics.DENSITY_HIGH) / 2;
|
||||
|
||||
if (0 == density) {
|
||||
return null;
|
||||
} else if (density < low) {
|
||||
return LOW;
|
||||
} else if (density > high) {
|
||||
return HIGH;
|
||||
}
|
||||
return MEDIUM;
|
||||
}
|
||||
|
||||
private String getDisplayWidth(DisplayMetrics displayMetrics) {
|
||||
return String.valueOf(displayMetrics.widthPixels);
|
||||
}
|
||||
|
||||
private String getDisplayHeight(DisplayMetrics displayMetrics) {
|
||||
return String.valueOf(displayMetrics.heightPixels);
|
||||
}
|
||||
|
||||
private String getClientSdk(String sdkPrefix) {
|
||||
if (sdkPrefix == null) {
|
||||
return Constants.CLIENT_SDK;
|
||||
} else {
|
||||
return String.format("%s@%s", sdkPrefix, Constants.CLIENT_SDK);
|
||||
}
|
||||
}
|
||||
|
||||
private String getMacSha1(String macAddress) {
|
||||
if (macAddress == null) {
|
||||
return null;
|
||||
}
|
||||
String macSha1 = sha1(macAddress);
|
||||
|
||||
return macSha1;
|
||||
}
|
||||
|
||||
private String getMacShortMd5(String macAddress) {
|
||||
if (macAddress == null) {
|
||||
return null;
|
||||
}
|
||||
String macShort = macAddress.replaceAll(":", "");
|
||||
String macShortMd5 = md5(macShort);
|
||||
|
||||
return macShortMd5;
|
||||
}
|
||||
|
||||
private String getAndroidId(Context context, boolean isGooglePlayServicesAvailable) {
|
||||
if (!isGooglePlayServicesAvailable) {
|
||||
return Reflection.getAndroidId(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String sha1(final String text) {
|
||||
return hash(text, SHA1);
|
||||
}
|
||||
|
||||
private String md5(final String text) {
|
||||
return hash(text, MD5);
|
||||
}
|
||||
|
||||
private String hash(final String text, final String method) {
|
||||
String hashString = null;
|
||||
try {
|
||||
final byte[] bytes = text.getBytes(ENCODING);
|
||||
final MessageDigest mesd = MessageDigest.getInstance(method);
|
||||
mesd.update(bytes, 0, bytes.length);
|
||||
final byte[] hash = mesd.digest();
|
||||
hashString = convertToHex(hash);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return hashString;
|
||||
}
|
||||
|
||||
private static String convertToHex(final byte[] bytes) {
|
||||
final BigInteger bigInt = new BigInteger(1, bytes);
|
||||
final String formatString = "%0" + (bytes.length << 1) + "x";
|
||||
return String.format(formatString, bigInt);
|
||||
}
|
||||
|
||||
private String getFacebookAttributionId(final Context context) {
|
||||
try {
|
||||
final ContentResolver contentResolver = context.getContentResolver();
|
||||
final Uri uri = Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider");
|
||||
final String columnName = "aid";
|
||||
final String[] projection = {columnName};
|
||||
final Cursor cursor = contentResolver.query(uri, projection, null, null, null);
|
||||
|
||||
if (null == cursor) {
|
||||
return null;
|
||||
}
|
||||
if (!cursor.moveToFirst()) {
|
||||
cursor.close();
|
||||
return null;
|
||||
}
|
||||
|
||||
final String attributionId = cursor.getString(cursor.getColumnIndex(columnName));
|
||||
cursor.close();
|
||||
return attributionId;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
mobile/android/thirdparty/com/adjust/sdk/IActivityHandler.java
vendored
Normal file
36
mobile/android/thirdparty/com/adjust/sdk/IActivityHandler.java
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by pfms on 15/12/14.
|
||||
*/
|
||||
public interface IActivityHandler {
|
||||
public void init(AdjustConfig config);
|
||||
|
||||
public void trackSubsessionStart();
|
||||
|
||||
public void trackSubsessionEnd();
|
||||
|
||||
public void trackEvent(AdjustEvent event);
|
||||
|
||||
public void finishedTrackingActivity(JSONObject jsonResponse);
|
||||
|
||||
public void setEnabled(boolean enabled);
|
||||
|
||||
public boolean isEnabled();
|
||||
|
||||
public void readOpenUrl(Uri url, long clickTime);
|
||||
|
||||
public boolean tryUpdateAttribution(AdjustAttribution attribution);
|
||||
|
||||
public void sendReferrer(String referrer, long clickTime);
|
||||
|
||||
public void setOfflineMode(boolean enabled);
|
||||
|
||||
public void setAskingAttribution(boolean askingAttribution);
|
||||
|
||||
public ActivityPackage getAttributionPackage();
|
||||
}
|
||||
20
mobile/android/thirdparty/com/adjust/sdk/IAttributionHandler.java
vendored
Normal file
20
mobile/android/thirdparty/com/adjust/sdk/IAttributionHandler.java
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by pfms on 15/12/14.
|
||||
*/
|
||||
public interface IAttributionHandler {
|
||||
public void init(IActivityHandler activityHandler,
|
||||
ActivityPackage attributionPackage,
|
||||
boolean startPaused);
|
||||
|
||||
public void getAttribution();
|
||||
|
||||
public void checkAttribution(JSONObject jsonResponse);
|
||||
|
||||
public void pauseSending();
|
||||
|
||||
public void resumeSending();
|
||||
}
|
||||
20
mobile/android/thirdparty/com/adjust/sdk/ILogger.java
vendored
Normal file
20
mobile/android/thirdparty/com/adjust/sdk/ILogger.java
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
public interface ILogger {
|
||||
public void setLogLevel(LogLevel logLevel);
|
||||
|
||||
public void setLogLevelString(String logLevelString);
|
||||
|
||||
public void verbose(String message, Object... parameters);
|
||||
|
||||
public void debug(String message, Object... parameters);
|
||||
|
||||
public void info(String message, Object... parameters);
|
||||
|
||||
public void warn(String message, Object... parameters);
|
||||
|
||||
public void error(String message, Object... parameters);
|
||||
|
||||
public void Assert(String message, Object... parameters);
|
||||
|
||||
}
|
||||
27
mobile/android/thirdparty/com/adjust/sdk/IPackageHandler.java
vendored
Normal file
27
mobile/android/thirdparty/com/adjust/sdk/IPackageHandler.java
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public interface IPackageHandler {
|
||||
public void init(IActivityHandler activityHandler, Context context, boolean startPaused);
|
||||
|
||||
public void addPackage(ActivityPackage pack);
|
||||
|
||||
public void sendFirstPackage();
|
||||
|
||||
public void sendNextPackage();
|
||||
|
||||
public void closeFirstPackage();
|
||||
|
||||
public void pauseSending();
|
||||
|
||||
public void resumeSending();
|
||||
|
||||
public String getFailureMessage();
|
||||
|
||||
public void finishedTrackingActivity(JSONObject jsonResponse);
|
||||
|
||||
public void sendClickPackage(ActivityPackage clickPackage);
|
||||
}
|
||||
9
mobile/android/thirdparty/com/adjust/sdk/IRequestHandler.java
vendored
Normal file
9
mobile/android/thirdparty/com/adjust/sdk/IRequestHandler.java
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
public interface IRequestHandler {
|
||||
public void init(IPackageHandler packageHandler);
|
||||
|
||||
public void sendPackage(ActivityPackage pack);
|
||||
|
||||
public void sendClickPackage(ActivityPackage clickPackage);
|
||||
}
|
||||
21
mobile/android/thirdparty/com/adjust/sdk/LICENSE
vendored
Normal file
21
mobile/android/thirdparty/com/adjust/sdk/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2012-2014 adjust GmbH,
|
||||
http://www.adjust.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
19
mobile/android/thirdparty/com/adjust/sdk/LogLevel.java
vendored
Normal file
19
mobile/android/thirdparty/com/adjust/sdk/LogLevel.java
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Created by pfms on 11/03/15.
|
||||
*/
|
||||
public enum LogLevel {
|
||||
VERBOSE(Log.VERBOSE), DEBUG(Log.DEBUG), INFO(Log.INFO), WARN(Log.WARN), ERROR(Log.ERROR), ASSERT(Log.ASSERT);
|
||||
final int androidLogLevel;
|
||||
|
||||
LogLevel(final int androidLogLevel) {
|
||||
this.androidLogLevel = androidLogLevel;
|
||||
}
|
||||
|
||||
public int getAndroidLogLevel() {
|
||||
return androidLogLevel;
|
||||
}
|
||||
}
|
||||
107
mobile/android/thirdparty/com/adjust/sdk/Logger.java
vendored
Normal file
107
mobile/android/thirdparty/com/adjust/sdk/Logger.java
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// Logger.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-04-18.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.adjust.sdk.Constants.LOGTAG;
|
||||
|
||||
public class Logger implements ILogger {
|
||||
|
||||
private LogLevel logLevel;
|
||||
private static String formatErrorMessage = "Error formating log message: %s, with params: %s";
|
||||
|
||||
public Logger() {
|
||||
setLogLevel(LogLevel.INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogLevel(LogLevel logLevel) {
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogLevelString(String logLevelString) {
|
||||
if (null != logLevelString) {
|
||||
try {
|
||||
setLogLevel(LogLevel.valueOf(logLevelString.toUpperCase(Locale.US)));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
error("Malformed logLevel '%s', falling back to 'info'", logLevelString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verbose(String message, Object... parameters) {
|
||||
if (logLevel.androidLogLevel <= Log.VERBOSE) {
|
||||
try {
|
||||
Log.v(LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message, Object... parameters) {
|
||||
if (logLevel.androidLogLevel <= Log.DEBUG) {
|
||||
try {
|
||||
Log.d(LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message, Object... parameters) {
|
||||
if (logLevel.androidLogLevel <= Log.INFO) {
|
||||
try {
|
||||
Log.i(LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String message, Object... parameters) {
|
||||
if (logLevel.androidLogLevel <= Log.WARN) {
|
||||
try {
|
||||
Log.w(LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Object... parameters) {
|
||||
if (logLevel.androidLogLevel <= Log.ERROR) {
|
||||
try {
|
||||
Log.e(LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Assert(String message, Object... parameters) {
|
||||
try {
|
||||
Log.println(Log.ASSERT, LOGTAG, String.format(message, parameters));
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters)));
|
||||
}
|
||||
}
|
||||
}
|
||||
5
mobile/android/thirdparty/com/adjust/sdk/OnAttributionChangedListener.java
vendored
Normal file
5
mobile/android/thirdparty/com/adjust/sdk/OnAttributionChangedListener.java
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
public interface OnAttributionChangedListener {
|
||||
public void onAttributionChanged(AdjustAttribution attribution);
|
||||
}
|
||||
291
mobile/android/thirdparty/com/adjust/sdk/PackageBuilder.java
vendored
Normal file
291
mobile/android/thirdparty/com/adjust/sdk/PackageBuilder.java
vendored
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
//
|
||||
// PackageBuilder.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
class PackageBuilder {
|
||||
private AdjustConfig adjustConfig;
|
||||
private DeviceInfo deviceInfo;
|
||||
private ActivityState activityState;
|
||||
private long createdAt;
|
||||
|
||||
// reattributions
|
||||
Map<String, String> extraParameters;
|
||||
AdjustAttribution attribution;
|
||||
String reftag;
|
||||
|
||||
private static ILogger logger = AdjustFactory.getLogger();
|
||||
|
||||
public PackageBuilder(AdjustConfig adjustConfig,
|
||||
DeviceInfo deviceInfo,
|
||||
ActivityState activityState,
|
||||
long createdAt) {
|
||||
this.adjustConfig = adjustConfig;
|
||||
this.deviceInfo = deviceInfo;
|
||||
this.activityState = activityState.clone();
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public ActivityPackage buildSessionPackage() {
|
||||
Map<String, String> parameters = getDefaultParameters();
|
||||
addDuration(parameters, "last_interval", activityState.lastInterval);
|
||||
addString(parameters, "default_tracker", adjustConfig.defaultTracker);
|
||||
|
||||
ActivityPackage sessionPackage = getDefaultActivityPackage();
|
||||
sessionPackage.setPath("/session");
|
||||
sessionPackage.setActivityKind(ActivityKind.SESSION);
|
||||
sessionPackage.setSuffix("");
|
||||
sessionPackage.setParameters(parameters);
|
||||
|
||||
return sessionPackage;
|
||||
}
|
||||
|
||||
public ActivityPackage buildEventPackage(AdjustEvent event) {
|
||||
Map<String, String> parameters = getDefaultParameters();
|
||||
addInt(parameters, "event_count", activityState.eventCount);
|
||||
addString(parameters, "event_token", event.eventToken);
|
||||
addDouble(parameters, "revenue", event.revenue);
|
||||
addString(parameters, "currency", event.currency);
|
||||
addMapJson(parameters, "callback_params", event.callbackParameters);
|
||||
addMapJson(parameters, "partner_params", event.partnerParameters);
|
||||
|
||||
ActivityPackage eventPackage = getDefaultActivityPackage();
|
||||
eventPackage.setPath("/event");
|
||||
eventPackage.setActivityKind(ActivityKind.EVENT);
|
||||
eventPackage.setSuffix(getEventSuffix(event));
|
||||
eventPackage.setParameters(parameters);
|
||||
|
||||
return eventPackage;
|
||||
}
|
||||
|
||||
public ActivityPackage buildClickPackage(String source, long clickTime) {
|
||||
Map<String, String> parameters = getDefaultParameters();
|
||||
|
||||
addString(parameters, "source", source);
|
||||
addDate(parameters, "click_time", clickTime);
|
||||
addString(parameters, "reftag", reftag);
|
||||
addMapJson(parameters, "params", extraParameters);
|
||||
injectAttribution(parameters);
|
||||
|
||||
ActivityPackage clickPackage = getDefaultActivityPackage();
|
||||
clickPackage.setPath("/sdk_click");
|
||||
clickPackage.setActivityKind(ActivityKind.CLICK);
|
||||
clickPackage.setSuffix("");
|
||||
clickPackage.setParameters(parameters);
|
||||
|
||||
return clickPackage;
|
||||
}
|
||||
|
||||
public ActivityPackage buildAttributionPackage() {
|
||||
Map<String, String> parameters = getIdsParameters();
|
||||
|
||||
ActivityPackage attributionPackage = getDefaultActivityPackage();
|
||||
attributionPackage.setPath("attribution"); // does not contain '/' because of Uri.Builder.appendPath
|
||||
attributionPackage.setActivityKind(ActivityKind.ATTRIBUTION);
|
||||
attributionPackage.setSuffix("");
|
||||
attributionPackage.setParameters(parameters);
|
||||
|
||||
return attributionPackage;
|
||||
}
|
||||
|
||||
private ActivityPackage getDefaultActivityPackage() {
|
||||
ActivityPackage activityPackage = new ActivityPackage();
|
||||
activityPackage.setClientSdk(deviceInfo.clientSdk);
|
||||
return activityPackage;
|
||||
}
|
||||
|
||||
private Map<String, String> getDefaultParameters() {
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
|
||||
injectDeviceInfo(parameters);
|
||||
injectConfig(parameters);
|
||||
injectActivityState(parameters);
|
||||
addDate(parameters, "created_at", createdAt);
|
||||
|
||||
// general
|
||||
checkDeviceIds(parameters);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private Map<String, String> getIdsParameters() {
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
|
||||
injectDeviceInfoIds(parameters);
|
||||
injectConfig(parameters);
|
||||
injectActivityStateIds(parameters);
|
||||
|
||||
checkDeviceIds(parameters);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private void injectDeviceInfo(Map<String, String> parameters) {
|
||||
injectDeviceInfoIds(parameters);
|
||||
addString(parameters, "fb_id", deviceInfo.fbAttributionId);
|
||||
addString(parameters, "package_name", deviceInfo.packageName);
|
||||
addString(parameters, "app_version", deviceInfo.appVersion);
|
||||
addString(parameters, "device_type", deviceInfo.deviceType);
|
||||
addString(parameters, "device_name", deviceInfo.deviceName);
|
||||
addString(parameters, "device_manufacturer", deviceInfo.deviceManufacturer);
|
||||
addString(parameters, "os_name", deviceInfo.osName);
|
||||
addString(parameters, "os_version", deviceInfo.osVersion);
|
||||
addString(parameters, "language", deviceInfo.language);
|
||||
addString(parameters, "country", deviceInfo.country);
|
||||
addString(parameters, "screen_size", deviceInfo.screenSize);
|
||||
addString(parameters, "screen_format", deviceInfo.screenFormat);
|
||||
addString(parameters, "screen_density", deviceInfo.screenDensity);
|
||||
addString(parameters, "display_width", deviceInfo.displayWidth);
|
||||
addString(parameters, "display_height", deviceInfo.displayHeight);
|
||||
fillPluginKeys(parameters);
|
||||
}
|
||||
|
||||
private void injectDeviceInfoIds(Map<String, String> parameters) {
|
||||
addString(parameters, "mac_sha1", deviceInfo.macSha1);
|
||||
addString(parameters, "mac_md5", deviceInfo.macShortMd5);
|
||||
addString(parameters, "android_id", deviceInfo.androidId);
|
||||
}
|
||||
|
||||
private void injectConfig(Map<String, String> parameters) {
|
||||
addString(parameters, "app_token", adjustConfig.appToken);
|
||||
addString(parameters, "environment", adjustConfig.environment);
|
||||
addBoolean(parameters, "device_known", adjustConfig.knownDevice);
|
||||
addBoolean(parameters, "needs_attribution_data", adjustConfig.hasListener());
|
||||
|
||||
String playAdId = Util.getPlayAdId(adjustConfig.context);
|
||||
addString(parameters, "gps_adid", playAdId);
|
||||
Boolean isTrackingEnabled = Util.isPlayTrackingEnabled(adjustConfig.context);
|
||||
addBoolean(parameters, "tracking_enabled", isTrackingEnabled);
|
||||
}
|
||||
|
||||
private void injectActivityState(Map<String, String> parameters) {
|
||||
injectActivityStateIds(parameters);
|
||||
addInt(parameters, "session_count", activityState.sessionCount);
|
||||
addInt(parameters, "subsession_count", activityState.subsessionCount);
|
||||
addDuration(parameters, "session_length", activityState.sessionLength);
|
||||
addDuration(parameters, "time_spent", activityState.timeSpent);
|
||||
}
|
||||
|
||||
private void injectActivityStateIds(Map<String, String> parameters) {
|
||||
addString(parameters, "android_uuid", activityState.uuid);
|
||||
}
|
||||
|
||||
private void injectAttribution(Map<String, String> parameters) {
|
||||
if (attribution == null) {
|
||||
return;
|
||||
}
|
||||
addString(parameters, "tracker", attribution.trackerName);
|
||||
addString(parameters, "campaign", attribution.campaign);
|
||||
addString(parameters, "adgroup", attribution.adgroup);
|
||||
addString(parameters, "creative", attribution.creative);
|
||||
}
|
||||
|
||||
private void checkDeviceIds(Map<String, String> parameters) {
|
||||
if (!parameters.containsKey("mac_sha1")
|
||||
&& !parameters.containsKey("mac_md5")
|
||||
&& !parameters.containsKey("android_id")
|
||||
&& !parameters.containsKey("gps_adid")) {
|
||||
logger.error("Missing device id's. Please check if Proguard is correctly set with Adjust SDK");
|
||||
}
|
||||
}
|
||||
|
||||
private void fillPluginKeys(Map<String, String> parameters) {
|
||||
if (deviceInfo.pluginKeys == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : deviceInfo.pluginKeys.entrySet()) {
|
||||
addString(parameters, entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private String getEventSuffix(AdjustEvent event) {
|
||||
if (event.revenue == null) {
|
||||
return String.format(" '%s'", event.eventToken);
|
||||
} else {
|
||||
return String.format(Locale.US, " (%.4f %s, '%s')", event.revenue, event.currency, event.eventToken);
|
||||
}
|
||||
}
|
||||
|
||||
private void addString(Map<String, String> parameters, String key, String value) {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.put(key, value);
|
||||
}
|
||||
|
||||
private void addInt(Map<String, String> parameters, String key, long value) {
|
||||
if (value < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String valueString = Long.toString(value);
|
||||
addString(parameters, key, valueString);
|
||||
}
|
||||
|
||||
private void addDate(Map<String, String> parameters, String key, long value) {
|
||||
if (value < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String dateString = Util.dateFormat(value);
|
||||
addString(parameters, key, dateString);
|
||||
}
|
||||
|
||||
private void addDuration(Map<String, String> parameters, String key, long durationInMilliSeconds) {
|
||||
if (durationInMilliSeconds < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
long durationInSeconds = (durationInMilliSeconds + 500) / 1000;
|
||||
addInt(parameters, key, durationInSeconds);
|
||||
}
|
||||
|
||||
private void addMapJson(Map<String, String> parameters, String key, Map<String, String> map) {
|
||||
if (map == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (map.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject jsonObject = new JSONObject(map);
|
||||
String jsonString = jsonObject.toString();
|
||||
|
||||
addString(parameters, key, jsonString);
|
||||
}
|
||||
|
||||
private void addBoolean(Map<String, String> parameters, String key, Boolean value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int intValue = value ? 1 : 0;
|
||||
|
||||
addInt(parameters, key, intValue);
|
||||
}
|
||||
|
||||
private void addDouble(Map<String, String> parameters, String key, Double value) {
|
||||
if (value == null) return;
|
||||
|
||||
String doubleString = String.format("%.5f", value);
|
||||
|
||||
addString(parameters, key, doubleString);
|
||||
}
|
||||
}
|
||||
274
mobile/android/thirdparty/com/adjust/sdk/PackageHandler.java
vendored
Normal file
274
mobile/android/thirdparty/com/adjust/sdk/PackageHandler.java
vendored
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
//
|
||||
// PackageHandler.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
// persistent
|
||||
public class PackageHandler extends HandlerThread implements IPackageHandler {
|
||||
private static final String PACKAGE_QUEUE_FILENAME = "AdjustIoPackageQueue";
|
||||
|
||||
private final InternalHandler internalHandler;
|
||||
private IRequestHandler requestHandler;
|
||||
private IActivityHandler activityHandler;
|
||||
private List<ActivityPackage> packageQueue;
|
||||
private AtomicBoolean isSending;
|
||||
private boolean paused;
|
||||
private Context context;
|
||||
private ILogger logger;
|
||||
|
||||
public PackageHandler(IActivityHandler activityHandler,
|
||||
Context context,
|
||||
boolean startPaused) {
|
||||
super(Constants.LOGTAG, MIN_PRIORITY);
|
||||
setDaemon(true);
|
||||
start();
|
||||
this.internalHandler = new InternalHandler(getLooper(), this);
|
||||
this.logger = AdjustFactory.getLogger();
|
||||
|
||||
init(activityHandler, context, startPaused);
|
||||
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.INIT;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IActivityHandler activityHandler, Context context, boolean startPaused) {
|
||||
this.activityHandler = activityHandler;
|
||||
this.context = context;
|
||||
this.paused = startPaused;
|
||||
}
|
||||
|
||||
// add a package to the queue
|
||||
@Override
|
||||
public void addPackage(ActivityPackage pack) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.ADD;
|
||||
message.obj = pack;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
// try to send the oldest package
|
||||
@Override
|
||||
public void sendFirstPackage() {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.SEND_FIRST;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
// remove oldest package and try to send the next one
|
||||
// (after success or possibly permanent failure)
|
||||
@Override
|
||||
public void sendNextPackage() {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.SEND_NEXT;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
// close the package to retry in the future (after temporary failure)
|
||||
@Override
|
||||
public void closeFirstPackage() {
|
||||
isSending.set(false);
|
||||
}
|
||||
|
||||
// interrupt the sending loop after the current request has finished
|
||||
@Override
|
||||
public void pauseSending() {
|
||||
paused = true;
|
||||
}
|
||||
|
||||
// allow sending requests again
|
||||
@Override
|
||||
public void resumeSending() {
|
||||
paused = false;
|
||||
}
|
||||
|
||||
// short info about how failing packages are handled
|
||||
@Override
|
||||
public String getFailureMessage() {
|
||||
return "Will retry later.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishedTrackingActivity(JSONObject jsonResponse) {
|
||||
activityHandler.finishedTrackingActivity(jsonResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendClickPackage(ActivityPackage clickPackage) {
|
||||
logger.debug("Sending click package (%s)", clickPackage);
|
||||
logger.verbose("%s", clickPackage.getExtendedString());
|
||||
requestHandler.sendClickPackage(clickPackage);
|
||||
}
|
||||
|
||||
private static final class InternalHandler extends Handler {
|
||||
private static final int INIT = 1;
|
||||
private static final int ADD = 2;
|
||||
private static final int SEND_NEXT = 3;
|
||||
private static final int SEND_FIRST = 4;
|
||||
|
||||
private final WeakReference<PackageHandler> packageHandlerReference;
|
||||
|
||||
protected InternalHandler(Looper looper, PackageHandler packageHandler) {
|
||||
super(looper);
|
||||
this.packageHandlerReference = new WeakReference<PackageHandler>(packageHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
super.handleMessage(message);
|
||||
|
||||
PackageHandler packageHandler = packageHandlerReference.get();
|
||||
if (null == packageHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.arg1) {
|
||||
case INIT:
|
||||
packageHandler.initInternal();
|
||||
break;
|
||||
case ADD:
|
||||
ActivityPackage activityPackage = (ActivityPackage) message.obj;
|
||||
packageHandler.addInternal(activityPackage);
|
||||
break;
|
||||
case SEND_FIRST:
|
||||
packageHandler.sendFirstInternal();
|
||||
break;
|
||||
case SEND_NEXT:
|
||||
packageHandler.sendNextInternal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// internal methods run in dedicated queue thread
|
||||
|
||||
private void initInternal() {
|
||||
requestHandler = AdjustFactory.getRequestHandler(this);
|
||||
|
||||
isSending = new AtomicBoolean();
|
||||
|
||||
readPackageQueue();
|
||||
}
|
||||
|
||||
private void addInternal(ActivityPackage newPackage) {
|
||||
packageQueue.add(newPackage);
|
||||
logger.debug("Added package %d (%s)", packageQueue.size(), newPackage);
|
||||
logger.verbose("%s", newPackage.getExtendedString());
|
||||
|
||||
writePackageQueue();
|
||||
}
|
||||
|
||||
private void sendFirstInternal() {
|
||||
if (packageQueue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (paused) {
|
||||
logger.debug("Package handler is paused");
|
||||
return;
|
||||
}
|
||||
if (isSending.getAndSet(true)) {
|
||||
logger.verbose("Package handler is already sending");
|
||||
return;
|
||||
}
|
||||
|
||||
ActivityPackage firstPackage = packageQueue.get(0);
|
||||
requestHandler.sendPackage(firstPackage);
|
||||
}
|
||||
|
||||
private void sendNextInternal() {
|
||||
packageQueue.remove(0);
|
||||
writePackageQueue();
|
||||
isSending.set(false);
|
||||
sendFirstInternal();
|
||||
}
|
||||
|
||||
private void readPackageQueue() {
|
||||
try {
|
||||
FileInputStream inputStream = context.openFileInput(PACKAGE_QUEUE_FILENAME);
|
||||
BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
|
||||
ObjectInputStream objectStream = new ObjectInputStream(bufferedStream);
|
||||
|
||||
try {
|
||||
Object object = objectStream.readObject();
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ActivityPackage> packageQueue = (List<ActivityPackage>) object;
|
||||
logger.debug("Package handler read %d packages", packageQueue.size());
|
||||
this.packageQueue = packageQueue;
|
||||
return;
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Failed to find package queue class");
|
||||
} catch (OptionalDataException e) {
|
||||
/* no-op */
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to read package queue object");
|
||||
} catch (ClassCastException e) {
|
||||
logger.error("Failed to cast package queue object");
|
||||
} finally {
|
||||
objectStream.close();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.verbose("Package queue file not found");
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to read package queue file");
|
||||
}
|
||||
|
||||
// start with a fresh package queue in case of any exception
|
||||
packageQueue = new ArrayList<ActivityPackage>();
|
||||
}
|
||||
|
||||
public static Boolean deletePackageQueue(Context context) {
|
||||
return context.deleteFile(PACKAGE_QUEUE_FILENAME);
|
||||
}
|
||||
|
||||
|
||||
private void writePackageQueue() {
|
||||
try {
|
||||
FileOutputStream outputStream = context.openFileOutput(PACKAGE_QUEUE_FILENAME, Context.MODE_PRIVATE);
|
||||
BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream);
|
||||
ObjectOutputStream objectStream = new ObjectOutputStream(bufferedStream);
|
||||
|
||||
try {
|
||||
objectStream.writeObject(packageQueue);
|
||||
logger.debug("Package handler wrote %d packages", packageQueue.size());
|
||||
} catch (NotSerializableException e) {
|
||||
logger.error("Failed to serialize packages");
|
||||
} finally {
|
||||
objectStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to write packages (%s)", e.getLocalizedMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
210
mobile/android/thirdparty/com/adjust/sdk/Reflection.java
vendored
Normal file
210
mobile/android/thirdparty/com/adjust/sdk/Reflection.java
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.adjust.sdk.plugin.Plugin;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.adjust.sdk.Constants.PLUGINS;
|
||||
|
||||
public class Reflection {
|
||||
|
||||
public static String getPlayAdId(Context context) {
|
||||
try {
|
||||
Object AdvertisingInfoObject = getAdvertisingInfoObject(context);
|
||||
|
||||
String playAdid = (String) invokeInstanceMethod(AdvertisingInfoObject, "getId", null);
|
||||
|
||||
return playAdid;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean isPlayTrackingEnabled(Context context) {
|
||||
try {
|
||||
Object AdvertisingInfoObject = getAdvertisingInfoObject(context);
|
||||
|
||||
Boolean isLimitedTrackingEnabled = (Boolean) invokeInstanceMethod(AdvertisingInfoObject, "isLimitAdTrackingEnabled", null);
|
||||
|
||||
return !isLimitedTrackingEnabled;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isGooglePlayServicesAvailable(Context context) {
|
||||
try {
|
||||
Integer isGooglePlayServicesAvailableStatusCode = (Integer) invokeStaticMethod(
|
||||
"com.google.android.gms.common.GooglePlayServicesUtil",
|
||||
"isGooglePlayServicesAvailable",
|
||||
new Class[]{Context.class}, context
|
||||
);
|
||||
|
||||
boolean isGooglePlayServicesAvailable = (Boolean) isConnectionResultSuccess(isGooglePlayServicesAvailableStatusCode);
|
||||
|
||||
return isGooglePlayServicesAvailable;
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMacAddress(Context context) {
|
||||
try {
|
||||
String macSha1 = (String) invokeStaticMethod(
|
||||
"com.adjust.sdk.plugin.MacAddressUtil",
|
||||
"getMacAddress",
|
||||
new Class[]{Context.class}, context
|
||||
);
|
||||
|
||||
return macSha1;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAndroidId(Context context) {
|
||||
try {
|
||||
String androidId = (String) invokeStaticMethod("com.adjust.sdk.plugin.AndroidIdUtil", "getAndroidId"
|
||||
, new Class[]{Context.class}, context);
|
||||
|
||||
return androidId;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSha1EmailAddress(Context context, String key) {
|
||||
try {
|
||||
String sha1EmailAddress = (String) invokeStaticMethod("com.adjust.sdk.plugin.EmailUtil", "getSha1EmailAddress"
|
||||
, new Class[]{Context.class, String.class}, context, key);
|
||||
|
||||
return sha1EmailAddress;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getAdvertisingInfoObject(Context context)
|
||||
throws Exception {
|
||||
return invokeStaticMethod("com.google.android.gms.ads.identifier.AdvertisingIdClient",
|
||||
"getAdvertisingIdInfo",
|
||||
new Class[]{Context.class}, context
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isConnectionResultSuccess(Integer statusCode) {
|
||||
if (statusCode == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Class ConnectionResultClass = Class.forName("com.google.android.gms.common.ConnectionResult");
|
||||
|
||||
Field SuccessField = ConnectionResultClass.getField("SUCCESS");
|
||||
|
||||
int successStatusCode = SuccessField.getInt(null);
|
||||
|
||||
return successStatusCode == statusCode;
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class forName(String className) {
|
||||
try {
|
||||
Class classObject = Class.forName(className);
|
||||
return classObject;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object createDefaultInstance(String className) {
|
||||
Class classObject = forName(className);
|
||||
Object instance = createDefaultInstance(classObject);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static Object createDefaultInstance(Class classObject) {
|
||||
try {
|
||||
Object instance = classObject.newInstance();
|
||||
return instance;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object createInstance(String className, Class[] cArgs, Object... args) {
|
||||
try {
|
||||
Class classObject = Class.forName(className);
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor constructor = classObject.getConstructor(cArgs);
|
||||
Object instance = constructor.newInstance(args);
|
||||
return instance;
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invokeStaticMethod(String className, String methodName, Class[] cArgs, Object... args)
|
||||
throws Exception {
|
||||
Class classObject = Class.forName(className);
|
||||
|
||||
return invokeMethod(classObject, methodName, null, cArgs, args);
|
||||
}
|
||||
|
||||
public static Object invokeInstanceMethod(Object instance, String methodName, Class[] cArgs, Object... args)
|
||||
throws Exception {
|
||||
Class classObject = instance.getClass();
|
||||
|
||||
return invokeMethod(classObject, methodName, instance, cArgs, args);
|
||||
}
|
||||
|
||||
public static Object invokeMethod(Class classObject, String methodName, Object instance, Class[] cArgs, Object... args)
|
||||
throws Exception {
|
||||
@SuppressWarnings("unchecked")
|
||||
Method methodObject = classObject.getMethod(methodName, cArgs);
|
||||
|
||||
Object resultObject = methodObject.invoke(instance, args);
|
||||
|
||||
return resultObject;
|
||||
}
|
||||
|
||||
public static Map<String, String> getPluginKeys(Context context) {
|
||||
Map<String, String> pluginKeys = new HashMap<String, String>();
|
||||
|
||||
for (Plugin plugin : getPlugins()) {
|
||||
Map.Entry<String, String> pluginEntry = plugin.getParameter(context);
|
||||
if (pluginEntry != null) {
|
||||
pluginKeys.put(pluginEntry.getKey(), pluginEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginKeys.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return pluginKeys;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Plugin> getPlugins() {
|
||||
List<Plugin> plugins = new ArrayList<Plugin>(PLUGINS.size());
|
||||
|
||||
for (String pluginName : PLUGINS) {
|
||||
Object pluginObject = Reflection.createDefaultInstance(pluginName);
|
||||
if (pluginObject != null && pluginObject instanceof Plugin) {
|
||||
plugins.add((Plugin) pluginObject);
|
||||
}
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
}
|
||||
210
mobile/android/thirdparty/com/adjust/sdk/RequestHandler.java
vendored
Normal file
210
mobile/android/thirdparty/com/adjust/sdk/RequestHandler.java
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
//
|
||||
// RequestHandler.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2013-06-25.
|
||||
// Copyright (c) 2013 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||
import ch.boye.httpclientandroidlib.NameValuePair;
|
||||
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
|
||||
import ch.boye.httpclientandroidlib.client.HttpClient;
|
||||
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpPost;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
|
||||
import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils;
|
||||
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class RequestHandler extends HandlerThread implements IRequestHandler {
|
||||
private InternalHandler internalHandler;
|
||||
private IPackageHandler packageHandler;
|
||||
private HttpClient httpClient;
|
||||
private ILogger logger;
|
||||
|
||||
public RequestHandler(IPackageHandler packageHandler) {
|
||||
super(Constants.LOGTAG, MIN_PRIORITY);
|
||||
setDaemon(true);
|
||||
start();
|
||||
|
||||
this.logger = AdjustFactory.getLogger();
|
||||
this.internalHandler = new InternalHandler(getLooper(), this);
|
||||
init(packageHandler);
|
||||
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.INIT;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(IPackageHandler packageHandler) {
|
||||
this.packageHandler = packageHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackage(ActivityPackage pack) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.SEND;
|
||||
message.obj = pack;
|
||||
internalHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendClickPackage(ActivityPackage clickPackage) {
|
||||
Message message = Message.obtain();
|
||||
message.arg1 = InternalHandler.SEND_CLICK;
|
||||
message.obj = clickPackage;
|
||||
internalHandler.sendMessage(message);
|
||||
|
||||
}
|
||||
|
||||
private static final class InternalHandler extends Handler {
|
||||
private static final int INIT = 72401;
|
||||
private static final int SEND = 72400;
|
||||
private static final int SEND_CLICK = 72402;
|
||||
|
||||
private final WeakReference<RequestHandler> requestHandlerReference;
|
||||
|
||||
protected InternalHandler(Looper looper, RequestHandler requestHandler) {
|
||||
super(looper);
|
||||
this.requestHandlerReference = new WeakReference<RequestHandler>(requestHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
super.handleMessage(message);
|
||||
|
||||
RequestHandler requestHandler = requestHandlerReference.get();
|
||||
if (null == requestHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.arg1) {
|
||||
case INIT:
|
||||
requestHandler.initInternal();
|
||||
break;
|
||||
case SEND:
|
||||
ActivityPackage activityPackage = (ActivityPackage) message.obj;
|
||||
requestHandler.sendInternal(activityPackage, true);
|
||||
break;
|
||||
case SEND_CLICK:
|
||||
ActivityPackage clickPackage = (ActivityPackage) message.obj;
|
||||
requestHandler.sendInternal(clickPackage, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initInternal() {
|
||||
httpClient = Util.getHttpClient();
|
||||
}
|
||||
|
||||
private void sendInternal(ActivityPackage activityPackage, boolean sendToPackageHandler) {
|
||||
try {
|
||||
HttpUriRequest request = getRequest(activityPackage);
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
requestFinished(response, sendToPackageHandler);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
sendNextPackage(activityPackage, "Failed to encode parameters", e, sendToPackageHandler);
|
||||
} catch (ClientProtocolException e) {
|
||||
closePackage(activityPackage, "Client protocol error", e, sendToPackageHandler);
|
||||
} catch (SocketTimeoutException e) {
|
||||
closePackage(activityPackage, "Request timed out", e, sendToPackageHandler);
|
||||
} catch (IOException e) {
|
||||
closePackage(activityPackage, "Request failed", e, sendToPackageHandler);
|
||||
} catch (Throwable e) {
|
||||
sendNextPackage(activityPackage, "Runtime exception", e, sendToPackageHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void requestFinished(HttpResponse response, boolean sendToPackageHandler) {
|
||||
JSONObject jsonResponse = Util.parseJsonResponse(response, logger);
|
||||
|
||||
if (jsonResponse == null) {
|
||||
if (sendToPackageHandler) {
|
||||
packageHandler.closeFirstPackage();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
packageHandler.finishedTrackingActivity(jsonResponse);
|
||||
if (sendToPackageHandler) {
|
||||
packageHandler.sendNextPackage();
|
||||
}
|
||||
}
|
||||
|
||||
// close current package because it failed
|
||||
private void closePackage(ActivityPackage activityPackage, String message, Throwable throwable, boolean sendToPackageHandler) {
|
||||
final String packageMessage = activityPackage.getFailureMessage();
|
||||
final String handlerMessage = packageHandler.getFailureMessage();
|
||||
final String reasonString = getReasonString(message, throwable);
|
||||
logger.error("%s. (%s) %s", packageMessage, reasonString, handlerMessage);
|
||||
|
||||
if (sendToPackageHandler) {
|
||||
packageHandler.closeFirstPackage();
|
||||
}
|
||||
}
|
||||
|
||||
// send next package because the current package failed
|
||||
private void sendNextPackage(ActivityPackage activityPackage, String message, Throwable throwable, boolean sendToPackageHandler) {
|
||||
final String failureMessage = activityPackage.getFailureMessage();
|
||||
final String reasonString = getReasonString(message, throwable);
|
||||
logger.error("%s. (%s)", failureMessage, reasonString);
|
||||
|
||||
if (sendToPackageHandler) {
|
||||
packageHandler.sendNextPackage();
|
||||
}
|
||||
}
|
||||
|
||||
private String getReasonString(String message, Throwable throwable) {
|
||||
if (throwable != null) {
|
||||
return String.format("%s: %s", message, throwable);
|
||||
} else {
|
||||
return String.format("%s", message);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpUriRequest getRequest(ActivityPackage activityPackage) throws UnsupportedEncodingException {
|
||||
String url = Constants.BASE_URL + activityPackage.getPath();
|
||||
HttpPost request = new HttpPost(url);
|
||||
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
request.addHeader("Client-SDK", activityPackage.getClientSdk());
|
||||
request.addHeader("Accept-Language", language);
|
||||
|
||||
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
|
||||
for (Map.Entry<String, String> entry : activityPackage.getParameters().entrySet()) {
|
||||
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue());
|
||||
pairs.add(pair);
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
String dateString = Util.dateFormat(now);
|
||||
NameValuePair sentAtPair = new BasicNameValuePair("sent_at", dateString);
|
||||
pairs.add(sentAtPair);
|
||||
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs);
|
||||
entity.setContentType(URLEncodedUtils.CONTENT_TYPE);
|
||||
request.setEntity(entity);
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
38
mobile/android/thirdparty/com/adjust/sdk/UnitTestActivity.java
vendored
Normal file
38
mobile/android/thirdparty/com/adjust/sdk/UnitTestActivity.java
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package com.adjust.sdk;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class UnitTestActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//setContentView(com.adjust.sdk.test.R.layout.activity_unit_test);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
//getMenuInflater().inflate(com.adjust.sdk.test.R.menu.menu_unit_test, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
/* int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == com.adjust.sdk.test.R.id.action_settings) {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
202
mobile/android/thirdparty/com/adjust/sdk/Util.java
vendored
Normal file
202
mobile/android/thirdparty/com/adjust/sdk/Util.java
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
//
|
||||
// Util.java
|
||||
// Adjust
|
||||
//
|
||||
// Created by Christian Wellenbrock on 2012-10-11.
|
||||
// Copyright (c) 2012-2014 adjust GmbH. All rights reserved.
|
||||
// See the file MIT-LICENSE for copying permission.
|
||||
//
|
||||
|
||||
package com.adjust.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||
import ch.boye.httpclientandroidlib.HttpStatus;
|
||||
import ch.boye.httpclientandroidlib.client.HttpClient;
|
||||
import ch.boye.httpclientandroidlib.params.BasicHttpParams;
|
||||
import ch.boye.httpclientandroidlib.params.HttpConnectionParams;
|
||||
import ch.boye.httpclientandroidlib.params.HttpParams;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Collects utility functions used by Adjust.
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
private static SimpleDateFormat dateFormat;
|
||||
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'Z";
|
||||
|
||||
protected static String createUuid() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public static String quote(String string) {
|
||||
if (string == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Pattern pattern = Pattern.compile("\\s");
|
||||
Matcher matcher = pattern.matcher(string);
|
||||
if (!matcher.find()) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return String.format("'%s'", string);
|
||||
}
|
||||
|
||||
public static String dateFormat(long date) {
|
||||
if (null == dateFormat) {
|
||||
dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
|
||||
}
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
public static String getPlayAdId(Context context) {
|
||||
return Reflection.getPlayAdId(context);
|
||||
}
|
||||
|
||||
public static Boolean isPlayTrackingEnabled(Context context) {
|
||||
return Reflection.isPlayTrackingEnabled(context);
|
||||
}
|
||||
|
||||
public static <T> T readObject(Context context, String filename, String objectName) {
|
||||
ILogger logger = AdjustFactory.getLogger();
|
||||
try {
|
||||
FileInputStream inputStream = context.openFileInput(filename);
|
||||
BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
|
||||
ObjectInputStream objectStream = new ObjectInputStream(bufferedStream);
|
||||
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
T t = (T) objectStream.readObject();
|
||||
logger.debug("Read %s: %s", objectName, t);
|
||||
return t;
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Failed to find %s class", objectName);
|
||||
} catch (OptionalDataException e) {
|
||||
/* no-op */
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to read %s object", objectName);
|
||||
} catch (ClassCastException e) {
|
||||
logger.error("Failed to cast %s object", objectName);
|
||||
} finally {
|
||||
objectStream.close();
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.verbose("%s file not found", objectName);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to open %s file for reading (%s)", objectName, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> void writeObject(T object, Context context, String filename, String objectName) {
|
||||
ILogger logger = AdjustFactory.getLogger();
|
||||
try {
|
||||
FileOutputStream outputStream = context.openFileOutput(filename, Context.MODE_PRIVATE);
|
||||
BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream);
|
||||
ObjectOutputStream objectStream = new ObjectOutputStream(bufferedStream);
|
||||
|
||||
try {
|
||||
objectStream.writeObject(object);
|
||||
logger.debug("Wrote %s: %s", objectName, object);
|
||||
} catch (NotSerializableException e) {
|
||||
logger.error("Failed to serialize %s", objectName);
|
||||
} finally {
|
||||
objectStream.close();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to open %s for writing (%s)", objectName, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String parseResponse(HttpResponse httpResponse, ILogger logger) {
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
httpResponse.getEntity().writeTo(out);
|
||||
out.close();
|
||||
String response = out.toString().trim();
|
||||
logger.verbose("Response: %s", response);
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to parse response (%s)", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static JSONObject parseJsonResponse(HttpResponse httpResponse, ILogger logger) {
|
||||
if (httpResponse == null) {
|
||||
return null;
|
||||
}
|
||||
String stringResponse = null;
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
httpResponse.getEntity().writeTo(out);
|
||||
out.close();
|
||||
stringResponse = out.toString().trim();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to parse response (%s)", e.getMessage());
|
||||
}
|
||||
|
||||
logger.verbose("Response: %s", stringResponse);
|
||||
if (stringResponse == null) return null;
|
||||
|
||||
JSONObject jsonResponse = null;
|
||||
try {
|
||||
jsonResponse = new JSONObject(stringResponse);
|
||||
} catch (JSONException e) {
|
||||
logger.error("Failed to parse json response: %s (%s)", stringResponse, e.getMessage());
|
||||
}
|
||||
|
||||
if (jsonResponse == null) return null;
|
||||
|
||||
String message = jsonResponse.optString("message", null);
|
||||
|
||||
if (message == null) {
|
||||
message = "No message found";
|
||||
}
|
||||
|
||||
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||
logger.info("%s", message);
|
||||
} else {
|
||||
logger.error("%s", message);
|
||||
}
|
||||
|
||||
return jsonResponse;
|
||||
}
|
||||
|
||||
public static HttpClient getHttpClient() {
|
||||
HttpParams httpParams = new BasicHttpParams();
|
||||
HttpConnectionParams.setConnectionTimeout(httpParams, Constants.CONNECTION_TIMEOUT);
|
||||
HttpConnectionParams.setSoTimeout(httpParams, Constants.SOCKET_TIMEOUT);
|
||||
return AdjustFactory.getHttpClient(httpParams);
|
||||
}
|
||||
|
||||
public static boolean checkPermission(Context context, String permission) {
|
||||
int result = context.checkCallingOrSelfPermission(permission);
|
||||
return result == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
10
mobile/android/thirdparty/com/adjust/sdk/plugin/AndroidIdUtil.java
vendored
Normal file
10
mobile/android/thirdparty/com/adjust/sdk/plugin/AndroidIdUtil.java
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package com.adjust.sdk.plugin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings.Secure;
|
||||
|
||||
public class AndroidIdUtil {
|
||||
public static String getAndroidId(final Context context) {
|
||||
return Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
|
||||
}
|
||||
}
|
||||
82
mobile/android/thirdparty/com/adjust/sdk/plugin/MacAddressUtil.java
vendored
Normal file
82
mobile/android/thirdparty/com/adjust/sdk/plugin/MacAddressUtil.java
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package com.adjust.sdk.plugin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MacAddressUtil {
|
||||
public static String getMacAddress(Context context) {
|
||||
final String rawAddress = getRawMacAddress(context);
|
||||
if (rawAddress == null) {
|
||||
return null;
|
||||
}
|
||||
final String upperAddress = rawAddress.toUpperCase(Locale.US);
|
||||
return removeSpaceString(upperAddress);
|
||||
}
|
||||
|
||||
private static String getRawMacAddress(Context context) {
|
||||
// android devices should have a wlan address
|
||||
final String wlanAddress = loadAddress("wlan0");
|
||||
if (wlanAddress != null) {
|
||||
return wlanAddress;
|
||||
}
|
||||
|
||||
// emulators should have an ethernet address
|
||||
final String ethAddress = loadAddress("eth0");
|
||||
if (ethAddress != null) {
|
||||
return ethAddress;
|
||||
}
|
||||
|
||||
// query the wifi manager (requires the ACCESS_WIFI_STATE permission)
|
||||
try {
|
||||
final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
final String wifiAddress = wifiManager.getConnectionInfo().getMacAddress();
|
||||
if (wifiAddress != null) {
|
||||
return wifiAddress;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String loadAddress(final String interfaceName) {
|
||||
try {
|
||||
final String filePath = "/sys/class/net/" + interfaceName + "/address";
|
||||
final StringBuilder fileData = new StringBuilder(1000);
|
||||
final BufferedReader reader = new BufferedReader(new FileReader(filePath), 1024);
|
||||
final char[] buf = new char[1024];
|
||||
int numRead;
|
||||
|
||||
String readData;
|
||||
while ((numRead = reader.read(buf)) != -1) {
|
||||
readData = String.valueOf(buf, 0, numRead);
|
||||
fileData.append(readData);
|
||||
}
|
||||
|
||||
reader.close();
|
||||
return fileData.toString();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String removeSpaceString(final String inputString) {
|
||||
if (inputString == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String outputString = inputString.replaceAll("\\s", "");
|
||||
if (TextUtils.isEmpty(outputString)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return outputString;
|
||||
}
|
||||
}
|
||||
12
mobile/android/thirdparty/com/adjust/sdk/plugin/Plugin.java
vendored
Normal file
12
mobile/android/thirdparty/com/adjust/sdk/plugin/Plugin.java
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package com.adjust.sdk.plugin;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by pfms on 18/09/14.
|
||||
*/
|
||||
public interface Plugin {
|
||||
Map.Entry<String, String> getParameter(Context context);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue