diff --git a/build.gradle b/build.gradle index 3d251c0..659d2db 100644 --- a/build.gradle +++ b/build.gradle @@ -2,9 +2,9 @@ apply plugin: 'com.android.library' android { compileSdkVersion 21 - buildToolsVersion "21.1.2" + buildToolsVersion "25.0.0" defaultConfig { - minSdkVersion 11 + minSdkVersion 14 targetSdkVersion 21 versionCode 1 versionName "1.0" @@ -25,7 +25,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:2.3.2' } } diff --git a/src/main/java/com/infinario/android/infinariosdk/CommandManager.java b/src/main/java/com/infinario/android/infinariosdk/CommandManager.java index 430e886..937e0e0 100644 --- a/src/main/java/com/infinario/android/infinariosdk/CommandManager.java +++ b/src/main/java/com/infinario/android/infinariosdk/CommandManager.java @@ -7,6 +7,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; + import java.util.Date; import java.util.HashSet; import java.util.List; @@ -17,23 +18,21 @@ */ public class CommandManager { - private static final int MAX_RETRIES = 20; - DbQueue queue; HttpHelper http; Preferences preferences; - Object lockFlush; + final Object lockFlush; boolean flushInProgress; boolean flushMayNeedRestart; AsyncTask flushTask; - public CommandManager(Context context, String target, String userAgent) { + public CommandManager(Context context, String target, String userAgent, Preferences preferences) { queue = new DbQueue(context); - preferences = Preferences.get(context); + this.preferences = preferences; http = new HttpHelper(target, userAgent); lockFlush = new Object(); - synchronized (lockFlush){ + synchronized (lockFlush) { flushInProgress = false; flushMayNeedRestart = false; } @@ -75,8 +74,8 @@ public boolean executeBatch() { StringBuilder logResult = new StringBuilder(); logResult.append("Batch executed, ") - .append(requests.size()) - .append(" prepared, "); + .append(requests.size()) + .append(" prepared, "); if (data != null) { @@ -105,17 +104,17 @@ public boolean executeBatch() { } } logResult.append(successfulRequests.size()) - .append(" succeeded, ") - .append(deleteRequests.size() - successfulRequests.size()); + .append(" succeeded, ") + .append(deleteRequests.size() - successfulRequests.size()); } else { Log.e(Contract.TAG, "Results are null"); logResult.append("0 succeeded, ") - .append(requests.size()); + .append(requests.size()); } } else { Log.e(Contract.TAG, "Data is null"); logResult.append("0 succeeded, ") - .append(requests.size()); + .append(requests.size()); } logResult.append(" failed, rest was told to retry"); @@ -154,8 +153,8 @@ private void flushCommands(int maxRetries) { synchronized (lockFlush) { if (!flushMayNeedRestart) { - flushInProgress = false; - break; + flushInProgress = false; + break; } flushMayNeedRestart = false; } @@ -183,8 +182,8 @@ private int exponentialIncrease(int timeInMiliseconds) int calculateDelay = timeInMiliseconds * 2; return Contract.FLUSH_MAX_INTERVAL < calculateDelay - ? Contract.FLUSH_MAX_INTERVAL - : calculateDelay; + ? Contract.FLUSH_MAX_INTERVAL + : calculateDelay; } private JSONObject setCookieId(JSONObject command) { diff --git a/src/main/java/com/infinario/android/infinariosdk/Contract.java b/src/main/java/com/infinario/android/infinariosdk/Contract.java index 64c87fb..819f765 100644 --- a/src/main/java/com/infinario/android/infinariosdk/Contract.java +++ b/src/main/java/com/infinario/android/infinariosdk/Contract.java @@ -1,8 +1,5 @@ package com.infinario.android.infinariosdk; -import android.app.AlarmManager; -import android.os.Build; - /** * This file has been created by igi on 1/14/15. */ @@ -19,6 +16,11 @@ public class Contract { public static final String VERSION = "1.1.4"; public static final String OS = "Android"; + /** + * Preference files -> each Infinario instance has it's own preferences + */ + public static final String SHARED_PREF_FILES = "shared_preference_files"; + /** * Preferences details */ @@ -74,7 +76,8 @@ public class Contract { public static final long FLUSH_DELAY = 10 * 1000; public static final int FLUSH_COUNT = 50; public static final boolean DEFAULT_AUTO_FLUSH = true; - public static int FLUSH_MIN_INTERVAL = 1000; + public static final java.lang.String PROJECT_PREFIX = "project_prefix"; + public static int FLUSH_MIN_INTERVAL = 1000; public static int FLUSH_MAX_INTERVAL = 3600000; /** @@ -97,13 +100,13 @@ public class Contract { public static final String COLUMN_COMMAND = "command"; public static final String COLUMN_RETRIES = "retries"; - public static final String DATABASE_NAME = "commands.db"; + public static final String DATABASE_NAME_POSTFIX = "commands.db"; public static final int DATABASE_VERSION = 1; // Database creation sql statement public static final String DATABASE_CREATE = "create table " - + TABLE_COMMANDS + "(" + COLUMN_ID - + " integer primary key autoincrement, " + COLUMN_COMMAND - + " text not null, " + COLUMN_RETRIES - + " integer not null default 0);"; + + TABLE_COMMANDS + "(" + COLUMN_ID + + " integer primary key autoincrement, " + COLUMN_COMMAND + + " text not null, " + COLUMN_RETRIES + + " integer not null default 0);"; } diff --git a/src/main/java/com/infinario/android/infinariosdk/DbHelper.java b/src/main/java/com/infinario/android/infinariosdk/DbHelper.java index 23ebeec..32e0575 100644 --- a/src/main/java/com/infinario/android/infinariosdk/DbHelper.java +++ b/src/main/java/com/infinario/android/infinariosdk/DbHelper.java @@ -10,8 +10,8 @@ */ public class DbHelper extends SQLiteOpenHelper { - public DbHelper(Context context) { - super(context, Contract.DATABASE_NAME, null, Contract.DATABASE_VERSION); + public DbHelper(Context context, String dbName) { + super(context, dbName, null, Contract.DATABASE_VERSION); } @Override @@ -22,10 +22,9 @@ public void onCreate(SQLiteDatabase database) { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(DbHelper.class.getName(), - "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); + "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + Contract.TABLE_COMMANDS); onCreate(db); } - } diff --git a/src/main/java/com/infinario/android/infinariosdk/DbQueue.java b/src/main/java/com/infinario/android/infinariosdk/DbQueue.java index 0a3dcc4..6e14916 100644 --- a/src/main/java/com/infinario/android/infinariosdk/DbQueue.java +++ b/src/main/java/com/infinario/android/infinariosdk/DbQueue.java @@ -4,9 +4,7 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabaseLockedException; import android.text.TextUtils; -import android.util.Log; import org.json.JSONException; @@ -24,8 +22,8 @@ public class DbQueue { private Object lockAccess; private int openCounter; - public DbQueue(Context context) { - dbHelper = new DbHelper(context); + public DbQueue(Context context, String dbName) { + dbHelper = new DbHelper(context, dbName); lockAccess = new Object(); openCounter = 0; } diff --git a/src/main/java/com/infinario/android/infinariosdk/GcmIntentService.java b/src/main/java/com/infinario/android/infinariosdk/GcmIntentService.java index 16f4182..5626f27 100644 --- a/src/main/java/com/infinario/android/infinariosdk/GcmIntentService.java +++ b/src/main/java/com/infinario/android/infinariosdk/GcmIntentService.java @@ -12,4 +12,4 @@ public GcmIntentService() { protected void onHandleIntent(Intent intent) { Infinario.handleGooglePushNotification(this, intent); } -} +} \ No newline at end of file diff --git a/src/main/java/com/infinario/android/infinariosdk/IabHelper.java b/src/main/java/com/infinario/android/infinariosdk/IabHelper.java index ad0fb1f..05e92de 100644 --- a/src/main/java/com/infinario/android/infinariosdk/IabHelper.java +++ b/src/main/java/com/infinario/android/infinariosdk/IabHelper.java @@ -27,8 +27,6 @@ import org.json.JSONException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/infinario/android/infinariosdk/Infinario.java b/src/main/java/com/infinario/android/infinariosdk/Infinario.java index 502bcb7..0b44f66 100644 --- a/src/main/java/com/infinario/android/infinariosdk/Infinario.java +++ b/src/main/java/com/infinario/android/infinariosdk/Infinario.java @@ -1,54 +1,25 @@ package com.infinario.android.infinariosdk; -import android.app.Activity; -import android.app.AlarmManager; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ComponentName; +import android.annotation.*; +import android.app.*; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.RemoteException; +import android.os.*; import android.provider.Settings; -import android.support.v4.app.NotificationCompat; -import android.util.DisplayMetrics; +import android.support.v4.app.*; +import android.text.TextUtils; import android.util.Log; -import com.google.android.gms.ads.identifier.AdvertisingIdClient; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GooglePlayServicesUtil; -import com.google.android.gms.gcm.GoogleCloudMessaging; +import android.support.annotation.NonNull; +import com.google.android.gms.common.*; +import com.google.android.gms.gcm.GoogleCloudMessaging; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HTTP; import org.json.JSONException; import org.json.JSONObject; -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; +import java.io.*; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -57,15 +28,15 @@ * This file has been created by Igor Liska on 1/8/15. */ public class Infinario { - private static Infinario instance = null; + private Object lockInstance = new Object(); private GoogleCloudMessaging gcm = null; - private String token; private String registrationId; private String userAgent; private Map customer; private CommandManager commandManager; private final Context context; + private final String projectToken; private int commandCounter = Contract.FLUSH_COUNT; private Preferences preferences; private IabHelper iabHelper = null; @@ -74,20 +45,20 @@ public class Infinario { private long sessionStart = -1; private long sessionEnd = -1; private long sessionTimeOut; - private Object lockPublic; - private Object lockFlushTimer; - private static Object lockInstance = new Object(); + private final Object lockPublic; + private final Object lockFlushTimer; private Handler sessionHandler; private Runnable sessionEndRunnable; private Runnable sessionFlushRunnable; private int sessionCounter; - private Infinario(Context context, String token, String target, Map customer) { - this.token = token; + private Infinario(Context context, String target, + Map customer, @NonNull String projectToken) { + this.context = context.getApplicationContext(); + this.projectToken = projectToken; - preferences = Preferences.get(context); - preferences.setToken(token); + preferences = new Preferences(context, projectToken); sessionProperties = new HashMap<>(); sessionTimeOut = Contract.SESSION_TIMEOUT; @@ -97,21 +68,19 @@ private Infinario(Context context, String token, String target, Map customer) { - if (instance == null) { - synchronized (lockInstance){ - if (instance == null){ - instance = new Infinario(context, token, target, customer); - } - } - } - - return instance; - } - - /** - * Obtains instance of Infinario instance to work with and identifies the customer. - * - * @param context application's context - * @param token project token obtained from Infinario admin - * @param target Infinario API location - * @param customer customer's registered ID - * @return Infinario instance - */ - @SuppressWarnings("unused") - public static Infinario getInstance(Context context, String token, String target, String customer) { - return getInstance(context, token, target, translateId(customer)); - } - - /** - * Obtains instance of Infinario instance to work with. - * - * @param context application's context - * @param token project token obtained from Infinario admin - * @param target Infinario API location - * @return Infinario instance - */ - @SuppressWarnings("unused") - public static Infinario getInstance(Context context, String token, String target) { - return getInstance(context, token, target, (Map) null); - } - - /** - * Obtains instance of Infinario instance to work with and identifies the customer. - * - * @param context application's context - * @param token project token obtained from Infinario admin - * @param customer key-value ids (cookie ID or registered ID) + * @param context application's context + * @param target Infinario API location + * @param projectToken Project token. * @return Infinario instance */ @SuppressWarnings("unused") - public static Infinario getInstance(Context context, String token, Map customer) { - return getInstance(context, token, null, customer); - } - - /** - * Obtains instance of Infinario instance to work with. - * - * @param context application's context - * @param token project token obtained from Infinario admin - * @return Infinario instance - */ - @SuppressWarnings("unused") - public static Infinario getInstance(Context context, String token) { - return getInstance(context, token, null, (Map) null); + public static Infinario getInstance(Context context, String target, String projectToken) { + return new Infinario(context, target, null, projectToken); } /** * Identifies a customer with their registered ID. * - * @param customer key-value ids (registered ID) + * @param customer key-value ids (registered ID) * @param properties key-value customer's properties */ @SuppressWarnings("unused") - public void identify(Map customer, Map properties) { + public void identify(Map customer, Map properties) { + synchronized (lockPublic) { if (customer.containsKey(Contract.REGISTERED)) { this.customer.put(Contract.REGISTERED, customer.get(Contract.REGISTERED)); + boolean isCustomerRegistered = !TextUtils.isEmpty(customer.get(Contract.REGISTERED)); - if (!customer.get(Contract.REGISTERED).equals(preferences.getRegistredId())){ + if (isCustomerRegistered) { preferences.setRegistredId(customer.get(Contract.REGISTERED)); Map identificationProperties = Device.deviceProperties(preferences); identificationProperties.put(Contract.REGISTERED, customer.get(Contract.REGISTERED)); @@ -249,7 +161,7 @@ public void identify(Map customer, Map propertie /** * Identifies a customer with their registered ID. * - * @param customer customer's registered ID + * @param customer customer's registered ID * @param properties key-value customer's properties */ @SuppressWarnings("unused") @@ -291,44 +203,46 @@ public boolean update(Map properties) { } private boolean _update(Map properties) { - if (commandManager.schedule(new Customer(customer, token, properties))) { - if (preferences.getAutomaticFlushing()) { - startFlushTimer(); - } + if (!commandManager.schedule(new Customer(customer, projectToken, properties))) { return true; } - return false; + if (preferences.getAutomaticFlushing()) { + startFlushTimer(); + } + + return true; } - private void sessionStart(long timeStamp, Map properties){ + private void sessionStart(long timeStamp, Map properties) { preferences.setSessionStart(timeStamp); _track("session_start", mergeProperties(properties, -1), timeStamp); } - private void sessionEnd(long timeStamp, long duration, Map properties){ + private void sessionEnd(long timeStamp, long duration, + Map properties) { _track("session_end", mergeProperties(properties, duration), timeStamp); preferences.setSessionStart(-1); preferences.setSessionEnd(-1, null); } - public void trackSessionStartImpl(){ + public void trackSessionStartImpl() { trackSessionStartImpl(null); } - public void trackSessionStartImpl(Map properties){ - synchronized (lockPublic){ + public void trackSessionStartImpl(Map properties) { + synchronized (lockPublic) { long now = (new Date()).getTime(); long sessionEnd = preferences.getSessionEnd(); long sessionStart = preferences.getSessionStart(); - if (sessionHandler != null){ + if (sessionHandler != null) { sessionHandler.removeCallbacks(sessionEndRunnable); } - if (sessionEnd != -1){ - if (now - sessionEnd > sessionTimeOut){ + if (sessionEnd != -1) { + if (now - sessionEnd > sessionTimeOut) { //Create session end sessionEnd(sessionEnd, (sessionEnd - sessionStart) / 1000L, preferences.getSessionEndProperties()); //Create session start @@ -336,7 +250,7 @@ public void trackSessionStartImpl(Map properties){ } else { //Continue in current session } - } else if (sessionStart == -1){ + } else if (sessionStart == -1) { //Create session start sessionStart(now, properties); } else if (now - sessionStart > sessionTimeOut) { @@ -348,12 +262,12 @@ public void trackSessionStartImpl(Map properties){ } } - public void trackSessionEndImpl(){ + public void trackSessionEndImpl() { trackSessionEndImpl(null); } - public void trackSessionEndImpl(Map properties){ - synchronized (lockPublic){ + public void trackSessionEndImpl(Map properties) { + synchronized (lockPublic) { //Save session end with current timestamp and start count TIMEOUT preferences.setSessionEnd((new Date()).getTime(), properties); sessionHandler.postDelayed(sessionEndRunnable, sessionTimeOut); @@ -361,35 +275,35 @@ public void trackSessionEndImpl(Map properties){ } public void setSessionTimeOut(long value) { - synchronized (lockPublic){ + synchronized (lockPublic) { sessionTimeOut = value; } } - public void trackSessionStart(){ + public void trackSessionStart() { trackSessionStart(null); } - public void trackSessionStart(Map properties){ + public void trackSessionStart(Map properties) { int _sessionCounter = 0; synchronized (lockPublic) { sessionCounter += 1; _sessionCounter = sessionCounter; } - if (_sessionCounter == 1){ + if (_sessionCounter == 1) { trackSessionStartImpl(properties); } } - public void trackSessionEnd(){ + public void trackSessionEnd() { trackSessionEnd(null); } - public void trackSessionEnd(Map properties){ + public void trackSessionEnd(Map properties) { int _sessionCounter = 0; - synchronized (lockPublic){ - if (sessionCounter > 0){ + synchronized (lockPublic) { + if (sessionCounter > 0) { sessionCounter -= 1; } _sessionCounter = sessionCounter; @@ -403,10 +317,10 @@ public void trackSessionEnd(Map properties){ private Map mergeProperties(Map properties, long duration) { Map deviceProperties = Device.deviceProperties(preferences); String appVersionName = preferences.getAppVersionName(); - if (appVersionName != null){ + if (appVersionName != null) { deviceProperties.put("app_version", appVersionName); } - if (duration != -1){ + if (duration != -1) { deviceProperties.put("duration", duration); } if (properties != null) { @@ -421,7 +335,7 @@ private Map mergeProperties(Map properties, long * * @param type event's type * @param properties event's properties - * @param timestamp event's timestamp in milliseconds since 1970-01-01 00:00:00 GMT + * @param timestamp event's timestamp in seconds * @return success of the operation */ public boolean track(String type, Map properties, Long timestamp) { @@ -431,15 +345,16 @@ public boolean track(String type, Map properties, Long timestamp } private boolean _track(String type, Map properties, Long timestamp) { - if (commandManager.schedule(new Event(customer, token, type, properties, timestamp))) { - if (preferences.getAutomaticFlushing()) { - startFlushTimer(); - } - return true; + if (!commandManager.schedule(new Event(customer, projectToken, type, properties, timestamp))) { + return false; + } + + if (preferences.getAutomaticFlushing()) { + startFlushTimer(); } - return false; + return true; } private boolean _track(String type, Map properties) { @@ -470,8 +385,8 @@ public boolean track(String type, Map properties) { /** * Tracks an event for a customer. Cannot be called prior to the identification. * - * @param type event's type - * @param timestamp event's timestamp in milliseconds since 1970-01-01 00:00:00 GMT + * @param type event's type + * @param timestamp event's timestamp in seconds * @return success of the operation */ public boolean track(String type, Long timestamp) { @@ -487,14 +402,7 @@ public void setSessionProperties(Map properties) { } } - /** - * @deprecated As of release 1.1.0, replaced by {@link #trackGooglePurchases(int resultCode, Intent data)} - */ - @Deprecated - public void trackPurchases(int resultCode, Intent data){ - this.trackGooglePurchases(resultCode, data); - } - + @SuppressLint("StaticFieldLeak") public void trackGooglePurchases(int resultCode, Intent data) { synchronized (lockPublic) { if (!iabHelper.setupDone() || data == null) { @@ -516,9 +424,9 @@ public void trackGooglePurchases(int resultCode, Intent data) { final Long purchaseTime = o.optLong("purchaseTime"); final String purchaseToken = o.optString("purchaseToken"); - new AsyncTask() { + new AsyncTask() { @Override - protected Void doInBackground(Void... params) { + protected Void doInBackground(String... params) { synchronized (lockPublic) { Log.d(Contract.TAG, "Purchased item " + productId + " at " + purchaseTime); @@ -530,8 +438,7 @@ protected Void doInBackground(Void... params) { if (details == null && iabHelper.subscriptionsSupported()) { details = iabHelper.querySkuDetails("subs", productId); } - } - catch (RemoteException | JSONException e) { + } catch (RemoteException | JSONException e) { return null; } @@ -551,30 +458,29 @@ protected Void doInBackground(Void... params) { return null; } } - }.execute(null, null, null); - } - catch (JSONException e) { + }.execute(); + } catch (JSONException e) { Log.e(Contract.TAG, "Cannot parse purchaseData"); } } } } - public void loadAmazonProduct(JSONObject amazonJsonProductDataResponse){ + public void loadAmazonProduct(JSONObject amazonJsonProductDataResponse) { synchronized (lockPublic) { amazonProduct = amazonJsonProductDataResponse; } } - public void trackAmazonPurchases(JSONObject amazonJsonPurchaseResponse){ + public void trackAmazonPurchases(JSONObject amazonJsonPurchaseResponse) { synchronized (lockPublic) { Map properties = Device.deviceProperties(preferences); properties.put("payment_system", "Amazon Store"); try { String sku = amazonJsonPurchaseResponse.getJSONObject("receipt").getString("sku"); - if (amazonProduct != null){ + if (amazonProduct != null) { try { - String [] priceCurrency = splitPriceAndCurrency(amazonProduct.getJSONObject("productData").getJSONObject(sku).getString("price")); + String[] priceCurrency = splitPriceAndCurrency(amazonProduct.getJSONObject("productData").getJSONObject(sku).getString("price")); properties.put("gross_amount", priceCurrency[1]); properties.put("currency", priceCurrency[0]); properties.put("product_title", amazonProduct.getJSONObject("productData").getJSONObject(sku).getString("title")); @@ -592,7 +498,8 @@ public void trackAmazonPurchases(JSONObject amazonJsonPurchaseResponse){ } } - public void trackVirtualPayment(String currency, int amount, String itemName, String itemType){ + public void trackVirtualPayment(String currency, int amount, String itemName, + String itemType) { synchronized (lockPublic) { Map virtualPayment = Device.deviceProperties(preferences); virtualPayment.put("currency", currency); @@ -603,35 +510,35 @@ public void trackVirtualPayment(String currency, int amount, String itemName, St } } - private void trackLogError(String tag, String message){ + private void trackLogError(String tag, String message) { trackLog("log_error", tag, message, null); } - private void trackLogError(String tag, String message, HashMap properties){ + private void trackLogError(String tag, String message, HashMap properties) { trackLog("log_error", tag, message, properties); } - private void trackLogWarning(String tag, String message){ + private void trackLogWarning(String tag, String message) { trackLog("log_warning", tag, message, null); } - private void trackLogWarning(String tag, String message, HashMap properties){ + private void trackLogWarning(String tag, String message, HashMap properties) { trackLog("log_warning", tag, message, properties); } - private void trackLogDebug(String tag, String message){ + private void trackLogDebug(String tag, String message) { trackLog("log_debug", tag, message, null); } - private void trackLogDebug(String tag, String message, HashMap properties){ + private void trackLogDebug(String tag, String message, HashMap properties) { trackLog("log_debug", tag, message, properties); } - private void trackLog(String type, String tag, String message, HashMap properties){ + private void trackLog(String type, String tag, String message, HashMap properties) { HashMap logMessage = new HashMap<>(); logMessage.put("tag", tag); logMessage.put("message", message); - if (properties != null){ + if (properties != null) { logMessage.putAll(properties); } track(type, logMessage); @@ -640,19 +547,20 @@ private void trackLog(String type, String tag, String message, HashMap(){ + if (preferences.getTarget().startsWith("https")) { + new AsyncTask() { @Override protected JSONObject doInBackground(Void... params) { HttpHelper http; - synchronized (lockPublic){ - http = new HttpHelper(Preferences.get(context).getTarget(), userAgent) - .addRequestProperty("X-Infinario-Secret", projectSecretToken) - .setTimeout(2000); + synchronized (lockPublic) { + http = new HttpHelper(preferences.getTarget(), userAgent) + .addRequestProperty("X-Infinario-Secret", projectSecretToken) + .setTimeout(2000); } try { @@ -676,9 +584,9 @@ protected JSONObject doInBackground(Void... params) { } @Override - protected void onPostExecute(JSONObject result){ - if (result != null){ - if (result.optBoolean("success")){ + protected void onPostExecute(JSONObject result) { + if (result != null) { + if (result.optBoolean("success")) { listener.onSegmentReceive(true, new InfinarioSegment().setName(result.optString("segment")), null); } else { listener.onSegmentReceive(false, null, "Unsuccesfull response"); @@ -725,10 +633,11 @@ public void disableAutomaticFlushing() { } /** - * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String senderId, int iconDrawable)} + * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String + * senderId, int iconDrawable)} */ @Deprecated - public void enablePushNotifications(String senderId, int iconDrawable){ + public void enablePushNotifications(String senderId, int iconDrawable) { this.enableGooglePushNotifications(senderId, iconDrawable); } @@ -757,18 +666,18 @@ public void enableGooglePushNotifications(String senderId, int iconDrawable) { } else { Log.i(Contract.TAG, "Already registered"); } - } - else { + } else { Log.i(Contract.TAG, "No valid Google Play Services APK found."); } } } /** - * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String senderId)} + * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String + * senderId)} */ @Deprecated - public void enablePushNotifications(String senderId){ + public void enablePushNotifications(String senderId) { this.enableGooglePushNotifications(senderId); } @@ -783,10 +692,11 @@ public void enableGooglePushNotifications(String senderId) { } /** - * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String senderId, String nameDrawable)} + * @deprecated As of release 1.1.0, replaced by {@link #enableGooglePushNotifications(String + * senderId, String nameDrawable)} */ @Deprecated - public void enablePushNotifications(String senderId, String nameDrawable){ + public void enablePushNotifications(String senderId, String nameDrawable) { this.enableGooglePushNotifications(senderId, nameDrawable); } @@ -796,10 +706,10 @@ public void enableGooglePushNotifications(String senderId, String nameDrawable) } /** - * @deprecated As of release 1.1.0, replaced by {@link #disableGooglePushNotifications()} + * @deprecated As of release 1.1.0, replaced by {@link #disableGooglePushNotifications()} */ @Deprecated - public void disablePushNotifications(){ + public void disablePushNotifications() { this.disableGooglePushNotifications(); } @@ -815,12 +725,12 @@ public void disableGooglePushNotifications() { /** * Handles intent (GCM message) from the GcmBroadcastReceiver for all Infinario instances. - * - * @param context application's context + * @param context application's context * @param intent received intent from a broadcast receiver. */ public static void handleGooglePushNotification(Context context, Intent intent) { - Preferences preferences = Preferences.get(context); + String projectPrefix = intent.getExtras().getString(Contract.PROJECT_PREFIX); + Preferences preferences = new Preferences(context, projectPrefix); if (preferences.getGooglePushNotifications() && checkPlayServices(context)) { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); @@ -889,6 +799,7 @@ private static boolean checkPlayServices(Context context) { * Stores the registration ID and the app versionCode in the application's * shared preferences. */ + @SuppressLint("StaticFieldLeak") private void registerInBackground() { new AsyncTask() { @Override @@ -896,6 +807,8 @@ protected Void doInBackground(Void... params) { try { registrationId = gcm.register(preferences.getSenderId()); + Log.d(Contract.TAG, "doInBackground(): registrationId: " + registrationId); + sendRegistrationIdToBackend(); preferences.setRegistrationId(registrationId); } catch (IOException ex) { @@ -955,12 +868,12 @@ private static void sendNotification(Context context, Bundle data, int iconDrawa /** * @return return drawable id by string */ - private int getDrawableId(String nameDrawable){ + private int getDrawableId(String nameDrawable) { try { return context.getResources().getIdentifier(nameDrawable, "drawable", context.getPackageName()); } catch (Exception e) { Log.e(Contract.TAG, "Cannot find drawable with name " + nameDrawable); - if (!nameDrawable.equals("infinario_notification_icon")){ + if (!nameDrawable.equals("infinario_notification_icon")) { return getDrawableId("infinario_notification_icon"); } else { return -1; @@ -968,51 +881,29 @@ private int getDrawableId(String nameDrawable){ } } - /** - * initializes google advertising ID - */ - private void initializeGoogleAdvertisingId(){ - new Thread(new Runnable() { - public void run() { - try { - AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context); - preferences.setGoogleAdvertisingId(adInfo.getId()); - - synchronized (lockPublic) { - HashMap advId = new HashMap(); - advId.put(Contract.PROPERTY_GOOGLE_ADV_ID,adInfo.getId()); - _update(advId); - } - } catch (Exception e) { - Log.e(Contract.TAG, "Cannot initialize google advertising ID"); - } - } - }).start(); - } - /** * Split string where is Price and Currency together. */ - private String[] splitPriceAndCurrency(String price){ + private String[] splitPriceAndCurrency(String price) { StringBuilder currency = new StringBuilder(); - for (int i=0;i= - Configuration.SCREENLAYOUT_SIZE_LARGE); + Configuration.SCREENLAYOUT_SIZE_MASK) >= + Configuration.SCREENLAYOUT_SIZE_LARGE); if (device_large) { Log.d(Contract.TAG, "Detect tablet"); @@ -1021,7 +912,7 @@ private void initializeDeviceType() { Log.d(Contract.TAG, "Detect mobile"); preferences.setDeviceType("mobile"); } - } catch (Exception e){ + } catch (Exception e) { Log.e(Contract.TAG, "Cannot initialize device type"); } } @@ -1029,22 +920,22 @@ private void initializeDeviceType() { /** * Listnener for segmentation */ - public interface SegmentListener{ + public interface SegmentListener { void onSegmentReceive(boolean wasSuccessful, InfinarioSegment segment, String error); } - private void startFlushTimer(){ - synchronized (lockFlushTimer){ - if (sessionHandler != null){ + private void startFlushTimer() { + synchronized (lockFlushTimer) { + if (sessionHandler != null) { stopFlushTimer(); sessionHandler.postDelayed(sessionFlushRunnable, Contract.FLUSH_DELAY); } } } - private void stopFlushTimer(){ - synchronized (lockFlushTimer){ - if(sessionHandler != null){ + private void stopFlushTimer() { + synchronized (lockFlushTimer) { + if (sessionHandler != null) { sessionHandler.removeCallbacks(sessionFlushRunnable); } } diff --git a/src/main/java/com/infinario/android/infinariosdk/Preferences.java b/src/main/java/com/infinario/android/infinariosdk/Preferences.java index 0a16d25..aa4a292 100644 --- a/src/main/java/com/infinario/android/infinariosdk/Preferences.java +++ b/src/main/java/com/infinario/android/infinariosdk/Preferences.java @@ -1,19 +1,19 @@ package com.infinario.android.infinariosdk; -import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Log; +import android.support.annotation.NonNull; + import org.json.JSONException; import org.json.JSONObject; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.UUID; /** * This file has been created by igi on 2/18/15. @@ -21,27 +21,22 @@ public class Preferences { private Context context; - private static Preferences instance = null; - private static Object lockInstance = new Object(); - private Object lockAccess; + private static final Object lockInstance = new Object(); + private final Object lockAccess; + private final String mProjectPrefix; - private Preferences(Context context) { + /** + * Constructor + * + * @param context Application context. + * @param projectPrefix Project prefix to distinguish Infinario instances. + */ + public Preferences(Context context, @NonNull String projectPrefix) { this.context = context; + mProjectPrefix = projectPrefix; lockAccess = new Object(); } - public static Preferences get(Context context) { - if (instance == null) { - synchronized (lockInstance) { - if (instance == null) { - instance = new Preferences(context); - } - } - } - - return instance; - } - /** * @param context application's context. * @return Application's {@code SharedPreferences}. @@ -49,6 +44,27 @@ public static Preferences get(Context context) { private SharedPreferences getPreferences(Context context) { // This sample app persists the registration ID in shared preferences, but // how you store the regID in your app is up to you. + + // Every Infinario instance has it's own shared preferences + String sharedPreferencesFileName = String.format( + "%s-%s", mProjectPrefix, Contract.PROPERTY); + + synchronized (lockAccess) { + return context.getSharedPreferences(sharedPreferencesFileName, Context.MODE_PRIVATE); + } + } + + /** + * Base infinario preferences to store properties + * that are common to many infinario projects + * + * @param context Application context. + * @return Base infinario SharedPreferences which is not project related + */ + private SharedPreferences getBasePreferences(Context context) { + // This sample app persists the registration ID in shared preferences, but + // how you store the regID in your app is up to you. + synchronized (lockAccess) { return context.getSharedPreferences(Contract.PROPERTY, Context.MODE_PRIVATE); } @@ -60,7 +76,7 @@ private SharedPreferences getPreferences(Context context) { * @return sender ID or project number obtained from Google Developers Console */ public String getSenderId() { - return getPreferences(context).getString(Contract.PROPERTY_SENDER_ID, null); + return getBasePreferences(context).getString(Contract.PROPERTY_SENDER_ID, null); } /** @@ -69,7 +85,7 @@ public String getSenderId() { * @param senderId sender ID or project number obtained from Google Developers Console */ public void setSenderId(String senderId) { - getPreferences(context).edit().putString(Contract.PROPERTY_SENDER_ID, senderId).commit(); + getBasePreferences(context).edit().putString(Contract.PROPERTY_SENDER_ID, senderId).commit(); } /** @@ -78,7 +94,7 @@ public void setSenderId(String senderId) { * @return referrer */ public String getReferrer() { - return getPreferences(context).getString(Contract.PROPERTY_REFERRER, null); + return getBasePreferences(context).getString(Contract.PROPERTY_REFERRER, null); } /** @@ -87,7 +103,7 @@ public String getReferrer() { * @param referrer referrer from INSTALL_REFERRER intent */ public void setReferrer(String referrer) { - getPreferences(context).edit().putString(Contract.PROPERTY_REFERRER, referrer).commit(); + getBasePreferences(context).edit().putString(Contract.PROPERTY_REFERRER, referrer).commit(); } /** @@ -108,24 +124,6 @@ public void setIcon(int iconDrawable) { getPreferences(context).edit().putInt(Contract.PROPERTY_ICON, iconDrawable).commit(); } - /** - * Gets token from preferences. - * - * @return token - */ - public String getToken() { - return getPreferences(context).getString(Contract.PROPERTY_TOKEN, null); - } - - /** - * Stores token in preferences. - * - * @param token token - */ - public void setToken(String token) { - getPreferences(context).edit().putString(Contract.PROPERTY_TOKEN, token).commit(); - } - /** * Gets target (Infinario API location) from preferences. * @@ -214,7 +212,8 @@ public void setSessionEnd(long value, Map properties) { * @return true if google push notifications are enabled, false otherwise */ public boolean getGooglePushNotifications() { - return getPreferences(context).getBoolean(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS, Contract.DEFAULT_PUSH_NOTIFICATIONS); + return getPreferences(context).getBoolean(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS, + Contract.DEFAULT_PUSH_NOTIFICATIONS); } /** @@ -223,7 +222,8 @@ public boolean getGooglePushNotifications() { * @param value enabled / disabled */ public void setGooglePushNotifications(boolean value) { - getPreferences(context).edit().putBoolean(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS, value).commit(); + getPreferences(context).edit().putBoolean(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS, value) + .commit(); } /** @@ -267,10 +267,10 @@ public void setRegistrationId(String registrationId) { Log.i(Contract.TAG, "Saving regId on app version " + appVersion); getPreferences(context) - .edit() - .putString(Contract.PROPERTY_REG_ID, registrationId) - .putInt(Contract.PROPERTY_APP_VERSION, appVersion) - .commit(); + .edit() + .putString(Contract.PROPERTY_REG_ID, registrationId) + .putInt(Contract.PROPERTY_APP_VERSION, appVersion) + .commit(); } /** @@ -373,19 +373,19 @@ public String getAppVersionName() { @SuppressWarnings("unused") public void clearStoredData() { getPreferences(context).edit() - .remove(Contract.PROPERTY_APP_VERSION) - .remove(Contract.PROPERTY_REG_ID) - .remove(Contract.PROPERTY_ICON) - .remove(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS) - .remove(Contract.PROPERTY_SENDER_ID) - .remove(Contract.PROPERTY_AUTO_FLUSH) - .remove(Contract.PROPERTY_SESSION_START) - .remove(Contract.PROPERTY_SESSION_END) - .remove(Contract.COOKIE) - .remove(Contract.CAMPAIGN_COOKIE) - .remove(Contract.PROPERTY_GOOGLE_ADV_ID) - .remove(Contract.PROPERTY_DEVICE_TYPE) - .commit(); + .remove(Contract.PROPERTY_APP_VERSION) + .remove(Contract.PROPERTY_REG_ID) + .remove(Contract.PROPERTY_ICON) + .remove(Contract.PROPERTY_GOOGLE_PUSH_NOTIFICATIONS) + .remove(Contract.PROPERTY_SENDER_ID) + .remove(Contract.PROPERTY_AUTO_FLUSH) + .remove(Contract.PROPERTY_SESSION_START) + .remove(Contract.PROPERTY_SESSION_END) + .remove(Contract.COOKIE) + .remove(Contract.CAMPAIGN_COOKIE) + .remove(Contract.PROPERTY_GOOGLE_ADV_ID) + .remove(Contract.PROPERTY_DEVICE_TYPE) + .commit(); } private Map jsonToMap(String json){ diff --git a/src/main/java/com/infinario/android/infinariosdk/ReferrerReceiver.java b/src/main/java/com/infinario/android/infinariosdk/ReferrerReceiver.java index bd968b9..b9b1c30 100644 --- a/src/main/java/com/infinario/android/infinariosdk/ReferrerReceiver.java +++ b/src/main/java/com/infinario/android/infinariosdk/ReferrerReceiver.java @@ -47,6 +47,6 @@ private void saveReferrer(String rawReferrer, Context context) { return; } - Preferences.get(context).setReferrer(campaignId); + new Preferences(context, "").setReferrer(campaignId); } } \ No newline at end of file