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">
+
+
+
+
+
+
-
\ No newline at end of file
+
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 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