diff --git a/.gitignore b/.gitignore
index db2993cb0fb3edd0f1cae1955b381d67e569155e..5650451d904861618fcf335869ccdaef5b04eb0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,4 +58,5 @@ Thumbs.db
 *.ipr
 *~
 *.swp
-/*/build
\ No newline at end of file
+/*/build
+gradle.properties
diff --git a/app/build.gradle b/app/build.gradle
index 1e6370272bba0c772b0cc575c6a8653970b751bd..6c28f7201060b9f3ad4e8614a6898f3169da82c9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,15 @@ android {
         targetSdkVersion 19
     }
     buildTypes {
+        debug {
+            try {
+                buildConfigField 'String', 'OPEN_CELLID_API_KEY', '\"' + open_cellid_api_key + '\"'
+            } catch (MissingPropertyException e) {
+                buildConfigField 'String', 'OPEN_CELLID_API_KEY', '"NA"'
+            }
+        }
         release {
+            buildConfigField 'String', 'OPEN_CELLID_API_KEY', '"NA"'
             runProguard true
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
         }
diff --git a/app/src/main/java/com/SecUpwN/AIMSICD/service/CellTracker.java b/app/src/main/java/com/SecUpwN/AIMSICD/service/CellTracker.java
index 728108809bd15830b1b834a0e6cc053ee19d5d10..fe1a666b7f1eb05e45e48e1ef2bf230b218e5356 100644
--- a/app/src/main/java/com/SecUpwN/AIMSICD/service/CellTracker.java
+++ b/app/src/main/java/com/SecUpwN/AIMSICD/service/CellTracker.java
@@ -15,20 +15,8 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.support.v4.app.NotificationCompat;
-import android.telephony.CellIdentityCdma;
-import android.telephony.CellIdentityGsm;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityWcdma;
 import android.telephony.CellInfo;
-import android.telephony.CellInfoCdma;
-import android.telephony.CellInfoGsm;
-import android.telephony.CellInfoLte;
-import android.telephony.CellInfoWcdma;
 import android.telephony.CellLocation;
-import android.telephony.CellSignalStrengthCdma;
-import android.telephony.CellSignalStrengthGsm;
-import android.telephony.CellSignalStrengthLte;
-import android.telephony.CellSignalStrengthWcdma;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -40,10 +28,12 @@ import android.util.Log;
 import android.view.WindowManager;
 
 import com.SecUpwN.AIMSICD.AIMSICD;
+import com.SecUpwN.AIMSICD.BuildConfig;
 import com.SecUpwN.AIMSICD.R;
 import com.SecUpwN.AIMSICD.adapters.AIMSICDDbAdapter;
 import com.SecUpwN.AIMSICD.utils.Cell;
 import com.SecUpwN.AIMSICD.utils.Device;
+import com.SecUpwN.AIMSICD.utils.DeviceApi17;
 import com.SecUpwN.AIMSICD.utils.Helpers;
 
 import java.util.ArrayList;
@@ -56,7 +46,7 @@ import java.util.concurrent.TimeUnit;
  */
 public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeListener {
     public static final String TAG = "CellTracker";
-    public static String OCID_API_KEY = "NA";
+    public static String OCID_API_KEY = null; // see getOcidKey()
     private final int NOTIFICATION_ID = 1;
 
     private static TelephonyManager tm;
@@ -82,6 +72,7 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
     private boolean mChangedLAC;
     private Cell mMonitorCell;
     private boolean mTypeZeroSmsDetected;
+    private LinkedBlockingQueue<NeighboringCellInfo> neighboringCellBlockingQueue;
 
     private final AIMSICDDbAdapter dbHelper;
     private Context context;
@@ -247,7 +238,15 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
         } else if (key.equals(OCID_UPLOAD)) {
             OCID_UPLOAD_PREF = sharedPreferences.getBoolean(OCID_UPLOAD, false);
         } else if (key.equals(OCID_KEY)) {
-            OCID_API_KEY = sharedPreferences.getString(OCID_KEY, "NA");
+            getOcidKey();
+        }
+    }
+
+    public void getOcidKey() {
+        final String OCID_KEY = context.getString(R.string.pref_ocid_key);
+        OCID_API_KEY = prefs.getString(OCID_KEY, BuildConfig.OPEN_CELLID_API_KEY);
+        if (OCID_API_KEY.trim().length() == 0) {
+            OCID_API_KEY = BuildConfig.OPEN_CELLID_API_KEY;
         }
     }
 
@@ -261,57 +260,15 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
         neighboringCellInfo = tm.getNeighboringCellInfo();
         if (neighboringCellInfo.size() == 0) {
             // try to poll the neighboring cells for a few seconds
-            final LinkedBlockingQueue<NeighboringCellInfo> neighboringCellBlockingQueue =
+            neighboringCellBlockingQueue =
                     new LinkedBlockingQueue<>(100);
-            final PhoneStateListener listener = new PhoneStateListener() {
-                private void handle() {
-                    List<NeighboringCellInfo> neighboringCellInfo;
-                    neighboringCellInfo = tm.getNeighboringCellInfo();
-                    if (neighboringCellInfo.size() == 0) {
-                        return;
-                    }
-                    Log.i(TAG, "neighbouringCellInfo empty - event based polling succeeded!");
-                    tm.listen(this, PhoneStateListener.LISTEN_NONE);
-                    neighboringCellBlockingQueue.addAll(neighboringCellInfo);
-                }
-
-                @Override
-                public void onServiceStateChanged(ServiceState serviceState) {
-                    handle();
-                }
-
-                @Override
-                public void onDataConnectionStateChanged(int state) {
-                    handle();
-                }
-
-                @Override
-                public void onDataConnectionStateChanged(int state, int networkType) {
-                    handle();
-                }
-
-                @Override
-                public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-                    handle();
-                }
-
-                @Override
-                public void onCellInfoChanged(List<CellInfo> cellInfo) {
-                    handle();
-                }
-            };
             Log.i(TAG, "neighbouringCellInfo empty - start polling");
 
             //LISTEN_CELL_INFO added in API 17
             if (Build.VERSION.SDK_INT > 16) {
-                tm.listen(listener,
-                        PhoneStateListener.LISTEN_CELL_INFO
-                                | PhoneStateListener.LISTEN_CELL_LOCATION |
-                                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                                | PhoneStateListener.LISTEN_SERVICE_STATE |
-                                PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+                DeviceApi17.startListening(tm, phoneStatelistener);
             } else {
-                tm.listen(listener,
+                tm.listen(phoneStatelistener,
                         PhoneStateListener.LISTEN_CELL_LOCATION |
                                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                                 | PhoneStateListener.LISTEN_SERVICE_STATE |
@@ -362,6 +319,17 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
         return neighboringCells;
     }
 
+    private void handlePhoneStateChange() {
+        List<NeighboringCellInfo> neighboringCellInfo;
+        neighboringCellInfo = tm.getNeighboringCellInfo();
+        if (neighboringCellInfo.size() == 0) {
+            return;
+        }
+        Log.i(TAG, "neighbouringCellInfo empty - event based polling succeeded!");
+        tm.listen(phoneStatelistener, PhoneStateListener.LISTEN_NONE);
+        neighboringCellBlockingQueue.addAll(neighboringCellInfo);
+    }
+
     public void refreshDevice() {
         mDevice.refreshDeviceInfo(tm, context);
     }
@@ -405,7 +373,7 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
         }
         REFRESH_RATE = TimeUnit.SECONDS.toMillis(t);
 
-        OCID_API_KEY = prefs.getString(context.getString(R.string.pref_ocid_key), "NA");
+        getOcidKey();
 
         if (trackFemtoPref) {
             startTrackingFemto();
@@ -536,78 +504,7 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
     public void onLocationChanged(Location loc) {
 
         if (Build.VERSION.SDK_INT > 16) {
-            List<CellInfo> cellinfolist = tm.getAllCellInfo();
-            if (cellinfolist != null) {
-                for (final CellInfo cellinfo : cellinfolist) {
-                    if (cellinfo instanceof CellInfoGsm) {
-                        final CellSignalStrengthGsm signalStrengthGsm = ((CellInfoGsm) cellinfo)
-                                .getCellSignalStrength();
-                        final CellIdentityGsm identityGsm = ((CellInfoGsm) cellinfo)
-                                .getCellIdentity();
-                        if (identityGsm != null) {
-                            mDevice.mCell.setCID(identityGsm.getCid());
-                            mDevice.mCell.setLAC(identityGsm.getLac());
-                            mDevice.mCell.setMCC(identityGsm.getMcc());
-                            mDevice.mCell.setMNC(identityGsm.getMnc());
-                        }
-                        if (signalStrengthGsm != null) {
-                            mDevice.mCell.setDBM(signalStrengthGsm.getDbm());
-                        }
-                        break;
-                    } else if (cellinfo instanceof CellInfoCdma) {
-                        final CellSignalStrengthCdma signalStrengthCdma
-                                = ((CellInfoCdma) cellinfo)
-                                .getCellSignalStrength();
-                        final CellIdentityCdma identityCdma = ((CellInfoCdma) cellinfo)
-                                .getCellIdentity();
-                        if (identityCdma != null) {
-                            mDevice.mCell.setCID(identityCdma.getBasestationId());
-                            mDevice.mCell.setLAC(identityCdma.getNetworkId());
-                            mDevice.mCell.setMNC(identityCdma.getSystemId());
-                            mDevice.mCell.setSID(identityCdma.getSystemId());
-                        }
-
-                        if (signalStrengthCdma != null) {
-                            mDevice.setSignalDbm(signalStrengthCdma.getDbm());
-                        }
-                        break;
-                    } else if (cellinfo instanceof CellInfoLte) {
-                        final CellSignalStrengthLte signalStrengthLte = ((CellInfoLte) cellinfo)
-                                .getCellSignalStrength();
-                        final CellIdentityLte identityLte = ((CellInfoLte) cellinfo)
-                                .getCellIdentity();
-
-                        if (identityLte != null) {
-                            mDevice.mCell.setCID(identityLte.getPci());
-                            mDevice.mCell.setLAC(identityLte.getTac());
-                            mDevice.mCell.setMCC(identityLte.getMcc());
-                            mDevice.mCell.setMNC(identityLte.getMnc());
-                        }
-
-                        if (signalStrengthLte != null) {
-                            mDevice.setSignalDbm(signalStrengthLte.getDbm());
-                        }
-                        break;
-                    } else if (cellinfo instanceof CellInfoWcdma) {
-                        final CellSignalStrengthWcdma signalStrengthWcdma
-                                = ((CellInfoWcdma) cellinfo)
-                                .getCellSignalStrength();
-                        final CellIdentityWcdma identityWcdma = ((CellInfoWcdma) cellinfo)
-                                .getCellIdentity();
-                        if (identityWcdma != null) {
-                            mDevice.mCell.setCID(identityWcdma.getCid());
-                            mDevice.mCell.setLAC(identityWcdma.getLac());
-                            mDevice.mCell.setMCC(identityWcdma.getMcc());
-                            mDevice.mCell.setMNC(identityWcdma.getMnc());
-                        }
-
-                        if (signalStrengthWcdma != null) {
-                            mDevice.setSignalDbm(signalStrengthWcdma.getDbm());
-                        }
-                        break;
-                    }
-                }
-            }
+            DeviceApi17.loadCellInfo(tm, mDevice.mCell);
         }
 
         if (!mDevice.mCell.isValid()) {
@@ -997,4 +894,35 @@ public class CellTracker implements SharedPreferences.OnSharedPreferenceChangeLi
      *
      * Copyright (C) 2013 iSEC Partners
      */
+
+    final PhoneStateListener phoneStatelistener = new PhoneStateListener() {
+        private void handle() {
+            handlePhoneStateChange();
+        }
+
+        @Override
+        public void onServiceStateChanged(ServiceState serviceState) {
+            handle();
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state) {
+            handle();
+        }
+
+        @Override
+        public void onDataConnectionStateChanged(int state, int networkType) {
+            handle();
+        }
+
+        @Override
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            handle();
+        }
+
+        @Override
+        public void onCellInfoChanged(List<CellInfo> cellInfo) {
+            handle();
+        }
+    };
 }
diff --git a/app/src/main/java/com/SecUpwN/AIMSICD/utils/Device.java b/app/src/main/java/com/SecUpwN/AIMSICD/utils/Device.java
index 3db80aa556e4bb0b366ef8c5e1cbbdf9f5c5d7a5..2056bf1129eb907ed969ce2c52fc72b032dd1a8b 100644
--- a/app/src/main/java/com/SecUpwN/AIMSICD/utils/Device.java
+++ b/app/src/main/java/com/SecUpwN/AIMSICD/utils/Device.java
@@ -3,26 +3,11 @@ package com.SecUpwN.AIMSICD.utils;
 import android.content.Context;
 import android.location.Location;
 import android.os.Build;
-import android.telephony.CellIdentityCdma;
-import android.telephony.CellIdentityGsm;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityWcdma;
-import android.telephony.CellInfo;
-import android.telephony.CellInfoCdma;
-import android.telephony.CellInfoGsm;
-import android.telephony.CellInfoLte;
-import android.telephony.CellInfoWcdma;
-import android.telephony.CellSignalStrengthCdma;
-import android.telephony.CellSignalStrengthGsm;
-import android.telephony.CellSignalStrengthLte;
-import android.telephony.CellSignalStrengthWcdma;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import android.util.Log;
 
-import java.util.List;
-
 public class Device {
 
     private final String TAG = "AIMSICD";
@@ -68,75 +53,8 @@ public class Device {
         mRoaming = tm.isNetworkRoaming();
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-            try {
-                List<CellInfo> cellInfoList = tm.getAllCellInfo();
-                if (cellInfoList != null) {
-                    for (final CellInfo info : cellInfoList) {
-                        mCell = new Cell();
-                        //Network type
-                        mCell.setNetType(tm.getNetworkType());
-                        mNetType = getNetworkTypeName();
-                        if (info instanceof CellInfoGsm) {
-                            final CellSignalStrengthGsm gsm = ((CellInfoGsm) info)
-                                    .getCellSignalStrength();
-                            final CellIdentityGsm identityGsm = ((CellInfoGsm) info)
-                                    .getCellIdentity();
-                            //Signal Strength
-                            mCell.setDBM(gsm.getDbm());
-                            //Cell Identity
-                            mCell.setCID(identityGsm.getCid());
-                            mCell.setMCC(identityGsm.getMcc());
-                            mCell.setMNC(identityGsm.getMnc());
-                            mCell.setLAC(identityGsm.getLac());
-                        } else if (info instanceof CellInfoCdma) {
-                            final CellSignalStrengthCdma cdma = ((CellInfoCdma) info)
-                                    .getCellSignalStrength();
-                            final CellIdentityCdma identityCdma = ((CellInfoCdma) info)
-                                    .getCellIdentity();
-                            //Signal Strength
-                            mCell.setDBM(cdma.getDbm());
-                            //Cell Identity
-                            mCell.setCID(identityCdma.getBasestationId());
-                            mCell.setMNC(identityCdma.getSystemId());
-                            mCell.setLAC(identityCdma.getNetworkId());
-                            mCell.setSID(identityCdma.getSystemId());
-                        } else if (info instanceof CellInfoLte) {
-                            final CellSignalStrengthLte lte = ((CellInfoLte) info)
-                                    .getCellSignalStrength();
-                            final CellIdentityLte identityLte = ((CellInfoLte) info)
-                                    .getCellIdentity();
-                            //Signal Strength
-                            mCell.setDBM(lte.getDbm());
-                            mCell.setTimingAdvance(lte.getTimingAdvance());
-                            //Cell Identity
-                            mCell.setMCC(identityLte.getMcc());
-                            mCell.setMNC(identityLte.getMnc());
-                            mCell.setCID(identityLte.getCi());
-                        } else if  (info instanceof CellInfoWcdma) {
-                            final CellSignalStrengthWcdma wcdma = ((CellInfoWcdma) info)
-                                    .getCellSignalStrength();
-                            final CellIdentityWcdma identityWcdma = ((CellInfoWcdma) info)
-                                    .getCellIdentity();
-                            //Signal Strength
-                            mCell.setDBM(wcdma.getDbm());
-                            //Cell Identity
-                            mCell.setLAC(identityWcdma.getLac());
-                            mCell.setMCC(identityWcdma.getMcc());
-                            mCell.setMNC(identityWcdma.getMnc());
-                            mCell.setCID(identityWcdma.getCid());
-                            mCell.setPSC(identityWcdma.getPsc());
-                        } else {
-                            Log.i(TAG, "Unknown type of cell signal!" + "ClassName: " +
-                                    info.getClass().getSimpleName() + " ToString: " +
-                                    info.toString());
-                        }
-                        if (mCell.isValid())
-                            break;
-                    }
-                }
-            } catch (NullPointerException npe) {
-                Log.e(TAG, "Unable to obtain cell signal information", npe);
-            }
+            mNetType = getNetworkTypeName();
+            DeviceApi17.loadCellInfo(tm, mCell);
         }
 
         if (mCell == null)
@@ -436,6 +354,8 @@ public class Device {
      * @return string representing device Network Type
      */
     public String getNetworkTypeName() {
+        if (mCell == null) return "Unknown";
+
         switch (mCell.getNetType()) {
             case TelephonyManager.NETWORK_TYPE_1xRTT:
                 mNetType = "1xRTT";
diff --git a/app/src/main/java/com/SecUpwN/AIMSICD/utils/DeviceApi17.java b/app/src/main/java/com/SecUpwN/AIMSICD/utils/DeviceApi17.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd5a1abef6185d5eda421cf665311b44d5f52846
--- /dev/null
+++ b/app/src/main/java/com/SecUpwN/AIMSICD/utils/DeviceApi17.java
@@ -0,0 +1,111 @@
+package com.SecUpwN.AIMSICD.utils;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.telephony.CellIdentityCdma;
+import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityWcdma;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Created by toby on 10/10/14.
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+public class DeviceApi17 {
+    public static final String TAG = "DeviceApi18";
+
+    public static void loadCellInfo(TelephonyManager tm, Cell mCell) {
+        try {
+            List<CellInfo> cellInfoList = tm.getAllCellInfo();
+            if (cellInfoList != null) {
+                for (final CellInfo info : cellInfoList) {
+                    mCell = new Cell();
+                    //Network type
+                    mCell.setNetType(tm.getNetworkType());
+                    if (info instanceof CellInfoGsm) {
+                        final CellSignalStrengthGsm gsm = ((CellInfoGsm) info)
+                                .getCellSignalStrength();
+                        final CellIdentityGsm identityGsm = ((CellInfoGsm) info)
+                                .getCellIdentity();
+                        //Signal Strength
+                        mCell.setDBM(gsm.getDbm());
+                        //Cell Identity
+                        mCell.setCID(identityGsm.getCid());
+                        mCell.setMCC(identityGsm.getMcc());
+                        mCell.setMNC(identityGsm.getMnc());
+                        mCell.setLAC(identityGsm.getLac());
+                    } else if (info instanceof CellInfoCdma) {
+                        final CellSignalStrengthCdma cdma = ((CellInfoCdma) info)
+                                .getCellSignalStrength();
+                        final CellIdentityCdma identityCdma = ((CellInfoCdma) info)
+                                .getCellIdentity();
+                        //Signal Strength
+                        mCell.setDBM(cdma.getDbm());
+                        //Cell Identity
+                        mCell.setCID(identityCdma.getBasestationId());
+                        mCell.setMNC(identityCdma.getSystemId());
+                        mCell.setLAC(identityCdma.getNetworkId());
+                        mCell.setSID(identityCdma.getSystemId());
+                    } else if (info instanceof CellInfoLte) {
+                        final CellSignalStrengthLte lte = ((CellInfoLte) info)
+                                .getCellSignalStrength();
+                        final CellIdentityLte identityLte = ((CellInfoLte) info)
+                                .getCellIdentity();
+                        //Signal Strength
+                        mCell.setDBM(lte.getDbm());
+                        mCell.setTimingAdvance(lte.getTimingAdvance());
+                        //Cell Identity
+                        mCell.setMCC(identityLte.getMcc());
+                        mCell.setMNC(identityLte.getMnc());
+                        mCell.setCID(identityLte.getCi());
+                    } else if  (info instanceof CellInfoWcdma) {
+                        final CellSignalStrengthWcdma wcdma = ((CellInfoWcdma) info)
+                                .getCellSignalStrength();
+                        final CellIdentityWcdma identityWcdma = ((CellInfoWcdma) info)
+                                .getCellIdentity();
+                        //Signal Strength
+                        mCell.setDBM(wcdma.getDbm());
+                        //Cell Identity
+                        mCell.setLAC(identityWcdma.getLac());
+                        mCell.setMCC(identityWcdma.getMcc());
+                        mCell.setMNC(identityWcdma.getMnc());
+                        mCell.setCID(identityWcdma.getCid());
+                        mCell.setPSC(identityWcdma.getPsc());
+                    } else {
+                        Log.i(TAG, "Unknown type of cell signal!" + "ClassName: " +
+                                info.getClass().getSimpleName() + " ToString: " +
+                                info.toString());
+                    }
+                    if (mCell.isValid())
+                        break;
+                }
+            }
+        } catch (NullPointerException npe) {
+            Log.e(TAG, "Unable to obtain cell signal information", npe);
+        }
+
+    }
+
+    public static void startListening(TelephonyManager tm, PhoneStateListener listener) {
+        tm.listen(listener,
+                PhoneStateListener.LISTEN_CELL_INFO
+                        | PhoneStateListener.LISTEN_CELL_LOCATION |
+                        PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                        | PhoneStateListener.LISTEN_SERVICE_STATE |
+                        PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+    }
+}