diff --git a/.gitignore b/.gitignore
index b2ee79b..3004ced 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@ captures/
 
 # Keystore files
 *.jks
+*.keystore
 
 # vim
 *.swp
diff --git a/app/build.gradle b/app/build.gradle
index f1f2267..eef58f3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,17 +4,34 @@ android {
     compileSdkVersion 23
     buildToolsVersion "23.0.3"
 
+    signingConfigs {
+        config {
+            if(project.hasProperty('atgSigningConfigKeyPassword')) {
+                keyAlias 'AndroidTcpdumpGui'
+                keyPassword atgSigningConfigKeyPassword
+                storeFile file('../sign/release-keystore.keystore')
+                storePassword atgSigningConfigKeyPassword
+            }
+        }
+    }
+
     defaultConfig {
         applicationId "com.voxlearning.androidtcpdumpgui"
-        minSdkVersion 11
+        minSdkVersion 14
         targetSdkVersion 23
         versionCode 1
         versionName "1.0"
     }
+
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            signingConfig signingConfigs.config
+        }
+
+        debug {
+            signingConfig signingConfigs.config
         }
     }
 }
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 030443e..60336c6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,10 +4,16 @@
     package="com.voxlearning.androidtcpdumpgui">
 
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
 
+
     <!-- suppress DeprecatedClassUsageInspection -->
     <uses-permission android:name="android.permission.GET_TASKS" />
     <uses-permission
@@ -38,4 +44,4 @@
         <activity android:name=".ViewActivity"></activity>
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureFilePath.java b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureFilePath.java
index f006d88..c91222a 100644
--- a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureFilePath.java
+++ b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureFilePath.java
@@ -38,6 +38,7 @@ public class CaptureFilePath {
     static public final String FileName_Comment = "comment.txt";
     static public final String FileName_Apps = "apps.txt";
     static public final String FileName_Logs = "logs.txt";
+    static public final String FileName_Gps = "gps.txt";
     static public final String FileName_TcpdumpOut = "tcpdump.out.txt";
     static public final String FileName_Packets = "packets.pcap";
 
diff --git a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureManager.java b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureManager.java
index cc8e91c..629f028 100644
--- a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureManager.java
+++ b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureManager.java
@@ -8,7 +8,11 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.location.Location;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.os.Build;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.widget.Toast;
 
@@ -129,12 +133,12 @@ public void start(Context context, String intf, String expr) {
 
         if(!dirRunning.exists()) {
             Log.e(TAG, "can not mkdir " + dirRunning.getPath());
+            Toast.makeText(context, "Can not write to external storage. Broken sdcard or memory?", Toast.LENGTH_LONG).show();
             return;
         }
 
-
         try {
-            recordStart();
+            recordStart(context);
 
             String fnPackets = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_Packets);
             String fnTcpdumpOut = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_TcpdumpOut);
@@ -255,10 +259,44 @@ public void recordAppName(String appName) {
         recordLog("app: " + appName);
     }
 
-    private void recordStart() {
+    private void recordStart(Context context) {
         String fn = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_Start);
         Io.writeFile(fn, "" + System.currentTimeMillis());
-        recordLog("start");
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("; ")
+                .append("MODEL=").append(Build.MODEL).append("; ")
+                .append("SERIAL=").append(Build.SERIAL).append("\n")
+        ;
+        sb.append("FINGERPRINT=").append(Build.FINGERPRINT).append("\n");
+        sb.append("RadioVersion=").append(Build.getRadioVersion()).append("\n");
+
+        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        String tmDevice = "", tmSerial = "", androidId = "";
+        try {
+            tmDevice = tm.getDeviceId();
+        }catch (Exception ignored){}
+        try {
+            tmSerial = tm.getSimSerialNumber();
+        }catch (Exception ignored){}
+        try{
+            androidId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
+        }catch (Exception ignored){}
+
+        sb.append("DeviceId=").append(tmDevice).append("; ")
+                .append("AndroidId=").append(androidId).append("; ")
+                .append("SimSerialNumber=").append(tmSerial).append("\n");
+
+
+        NetworkInfo ni = null;
+        try {
+            ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+            ni = cm.getActiveNetworkInfo();
+        }
+        catch (Exception ignored) { }
+        sb.append("NetworkInfo=").append(ni == null ? "null" : ni.toString()).append("\n");
+
+        recordLog("start\n" + sb.toString());
     }
 
     private void recordStop() {
@@ -267,18 +305,19 @@ private void recordStop() {
         recordLog("stop");
     }
 
-    public void recordComment(String s) {
-        String fn = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_Comment);
-        Io.writeFileAppend(fn, nowLogString() + " " + s + "\n");
-        recordLog("comment: " + s);
-    }
-
     public void recordLog(String s) {
         String fn = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_Logs);
         Io.writeFileAppend(fn, nowLogString() + " " + s + "\n");
         Log.d(TAG, "recordLog: " + s);
     }
 
+    public void recordGps(Location location) {
+        String fn = CaptureFilePath.OutputDirRunningFilePath(CaptureFilePath.FileName_Gps);
+        String s = location == null ? "(unknown-location)" : location.toString();
+
+        Io.writeFileAppend(fn, nowLogString() + " " + s + "\n");
+        Log.d(TAG, "recordGps: " + s);
+    }
 
     static public class Stats {
         public long mStartTime;
diff --git a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureService.java b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureService.java
index f6a788e..b2ec9bb 100644
--- a/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureService.java
+++ b/app/src/main/java/com/voxlearning/androidtcpdumpgui/CaptureService.java
@@ -1,17 +1,27 @@
 package com.voxlearning.androidtcpdumpgui;
 
+import android.Manifest;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.SystemClock;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.app.AlertDialog;
 import android.util.Log;
 
-public class CaptureService extends Service {
+public class CaptureService extends Service implements LocationListener {
 
     static private final String TAG = "CaptureService";
 
@@ -23,6 +33,7 @@ public class CaptureService extends Service {
 
     private CaptureManager mCaptureManager;
     private AlarmManager mAlarmManager;
+    private LocationManager mLocationManager;
 
     static final public int AlarmInterval_RestartService = 30 * 1000;
     static final public int DelayInterval_PeriodWork = 5 * 1000;
@@ -33,21 +44,21 @@ public class CaptureService extends Service {
     public void onCreate() {
         mCaptureManager = new CaptureManager();
         mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
+        gpsStart();
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
 
         if (intent != null) {
-            if(ServiceAction_CaptureStart.equals(intent.getAction())) {
+            if (ServiceAction_CaptureStart.equals(intent.getAction())) {
                 Log.d(TAG, "capture start");
                 periodWork();
-            }
-            else if(ServiceAction_PeriodWork.equals(intent.getAction())) {
+            } else if (ServiceAction_PeriodWork.equals(intent.getAction())) {
                 Log.d(TAG, "period work");
                 periodWork();
-            }
-            else if(ServiceAction_CaptureStop.equals(intent.getAction())) {
+            } else if (ServiceAction_CaptureStop.equals(intent.getAction())) {
                 Log.d(TAG, "capture stop");
                 stopSelf();
             }
@@ -65,6 +76,67 @@ public IBinder onBind(Intent intent) {
         return null;
     }
 
+
+
+
+    private static final long GPS_MIN_DISTANCE_UPDATE = 10; // The minimum distance to change Updates in meters
+    private static final long GPS_MIN_DURATION_UPDATE = 30 * 1000; // The minimum time between updates in milliseconds
+
+    @Override
+    public void onLocationChanged(Location location) {
+        mCaptureManager.recordGps(location);
+    }
+
+    @Override
+    public void onStatusChanged(String provider, int status, Bundle extras) {
+        mCaptureManager.recordLog("gps status changed: provider=" + provider + ", status=" + status);
+    }
+
+    @Override
+    public void onProviderEnabled(String provider) {
+        gpsStop();
+        gpsStart();
+    }
+
+    @Override
+    public void onProviderDisabled(String provider) {
+        gpsStop();
+        gpsStart();
+    }
+
+    public void gpsStart() {
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+
+        if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+
+            mCaptureManager.recordLog("gps start with last known location:" + LocationManager.GPS_PROVIDER);
+            mCaptureManager.recordGps(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
+            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_MIN_DURATION_UPDATE, GPS_MIN_DISTANCE_UPDATE, this);
+
+        } else if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
+
+            mCaptureManager.recordLog("gps start with last known location:" + LocationManager.NETWORK_PROVIDER);
+            mCaptureManager.recordGps(mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
+            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_MIN_DURATION_UPDATE, GPS_MIN_DISTANCE_UPDATE, this);
+
+        }
+    }
+
+    public void gpsStop() {
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+
+        mCaptureManager.recordLog("gps stop");
+        mLocationManager.removeUpdates(this);
+    }
+
+
+
+
+
     static public class PeriodWorkHandler extends Handler {
 
         private Context mContext;
diff --git a/app/src/main/java/com/voxlearning/androidtcpdumpgui/MainActivity.java b/app/src/main/java/com/voxlearning/androidtcpdumpgui/MainActivity.java
index 255e986..e2cb83c 100644
--- a/app/src/main/java/com/voxlearning/androidtcpdumpgui/MainActivity.java
+++ b/app/src/main/java/com/voxlearning/androidtcpdumpgui/MainActivity.java
@@ -1,10 +1,15 @@
 package com.voxlearning.androidtcpdumpgui;
 
+import android.Manifest;
 import android.annotation.SuppressLint;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
 import android.os.Handler;
 import android.os.Looper;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
@@ -126,14 +131,18 @@ private void doStart() {
         startService(intent);
 
         mTimerUpdateUi.postDelayed();
+        updateUi();
     }
 
     private void doStop() {
         String captureName = mCaptureManager.stop(this);
+
         Intent intent = new Intent(this, CaptureService.class);
         intent.setAction(CaptureService.ServiceAction_CaptureStop);
         startService(intent);
 
+        updateUi();
+
         if(captureName != null) {
             ViewActivity.openCapture(this, captureName);
         }
@@ -145,6 +154,8 @@ protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
+        updateTitleWithVersion();
+
         mHandler = new Handler(Looper.getMainLooper());
         mTimerUpdateUi = new TimerUpdateUi();
         mCaptureManager = new CaptureManager();
@@ -192,7 +203,6 @@ public void onClick(View v) {
                 else {
                     doStart();
                 }
-                updateUi();
             }
         });
 
@@ -212,7 +222,7 @@ private void updateUi() {
         else {
             mButtonStartStop.setText("Start");
 
-            setTitle(R.string.app_name);
+            updateTitleWithVersion();
 
             File[] files = new File(CaptureFilePath.OutputDir("")).listFiles();
             List<String> names = new ArrayList<>();
@@ -242,6 +252,36 @@ protected void onResume() {
         super.onResume();
         updateUi();
         mTimerUpdateUi.postDelayed();
+
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+            new AlertDialog.Builder(this)
+                    .setTitle("Location")
+                    .setMessage("Please allow this app to use GPS & Network Location")
+                    .show();
+        }
+
+
+        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
+        boolean isGpsLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+
+        if(!isGpsLocationEnabled) {
+            new AlertDialog.Builder(this)
+                    .setTitle("Location").setMessage("GPS is not enabled. Do you want to go to settings menu?")
+                    .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+                            MainActivity.this.startActivity(intent);
+                        }
+                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    dialog.cancel();
+                }
+            }).show();
+        }
     }
 
+    private void updateTitleWithVersion() {
+        String s = getString(R.string.app_name);
+        setTitle(s + " (" + BuildConfig.VERSION_NAME + "/" + BuildConfig.VERSION_CODE + ")");
+    }
 }
diff --git a/app/src/main/java/com/voxlearning/androidtcpdumpgui/ViewActivity.java b/app/src/main/java/com/voxlearning/androidtcpdumpgui/ViewActivity.java
index 5689099..b07b2ad 100644
--- a/app/src/main/java/com/voxlearning/androidtcpdumpgui/ViewActivity.java
+++ b/app/src/main/java/com/voxlearning/androidtcpdumpgui/ViewActivity.java
@@ -213,6 +213,7 @@ private void doSaveCommentZipShare() {
                 dirCapture + "/" + CaptureFilePath.FileName_Stop,
                 dirCapture + "/" + CaptureFilePath.FileName_Apps,
                 dirCapture + "/" + CaptureFilePath.FileName_Comment,
+                dirCapture + "/" + CaptureFilePath.FileName_Gps,
                 dirCapture + "/" + CaptureFilePath.FileName_Logs,
                 dirCapture + "/" + CaptureFilePath.FileName_Packets,
                 dirCapture + "/" + CaptureFilePath.FileName_TcpdumpOut,
diff --git a/build.sh b/build.sh
index b6ae15e..2f56b22 100755
--- a/build.sh
+++ b/build.sh
@@ -18,7 +18,9 @@ fi
 
 echo "Assembling AndroidTcpdumpGui ..."
 if gradle :app:assembleRelease; then
-    cp app/build/outputs/apk/app-release-unsigned.apk ./AndroidTcpdumpGui.apk
+    if [ -f app/build/outputs/apk/app-release.apk ]; then
+        cp app/build/outputs/apk/app-release.apk ./AndroidTcpdumpGui.apk
+    fi
     echo "Done"
 else
     echo "Error"
diff --git a/app/tcpdump.txt b/doc/tcpdump.txt
similarity index 100%
rename from app/tcpdump.txt
rename to doc/tcpdump.txt