|
@@ -15,7 +15,6 @@ import android.content.DialogInterface;
|
|
|
import android.graphics.Color;
|
|
|
import android.location.Location;
|
|
|
import android.os.Bundle;
|
|
|
-import android.util.Log;
|
|
|
import android.view.InflateException;
|
|
|
import android.view.LayoutInflater;
|
|
|
import android.view.View;
|
|
@@ -53,12 +52,17 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
GooglePlayServicesClient.ConnectionCallbacks,
|
|
|
GooglePlayServicesClient.OnConnectionFailedListener,
|
|
|
LocationListener {
|
|
|
+
|
|
|
private static GoogleMap sMap = null;
|
|
|
+
|
|
|
private static View sView = null;
|
|
|
|
|
|
+ private static Thread mLoader = null;
|
|
|
+
|
|
|
private static HashMap<String, String> sMarkerIDToSSID = new HashMap<String, String>();
|
|
|
|
|
|
private LocationClient mLocationClient;
|
|
|
+
|
|
|
private static final LocationRequest REQUEST = LocationRequest.create()
|
|
|
.setExpirationDuration(5000) // 5 seconds
|
|
|
.setInterval(5000) // 5 seconds
|
|
@@ -103,7 +107,7 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
recordOverviewFragment.setGroupKey("ESSID");
|
|
|
|
|
|
MainActivity.getInstance().injectFragment(recordOverviewFragment, false);
|
|
|
- //recordOverviewFragment.showDetailsForSSID(getActivity(), ssid);
|
|
|
+ //recordOverviewFragment.showDetailsForSSID(getActivity(), ssid);
|
|
|
//}
|
|
|
}
|
|
|
|
|
@@ -136,7 +140,9 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
* easier to use than LatLng
|
|
|
*/
|
|
|
private class Point {
|
|
|
+
|
|
|
public double x, y;
|
|
|
+
|
|
|
public Point(double sx, double sy) {
|
|
|
x = sx;
|
|
|
y = sy;
|
|
@@ -149,10 +155,13 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
* see MAX_DISTANCE
|
|
|
*/
|
|
|
private class SSIDArea {
|
|
|
+
|
|
|
private Point mMinimum, mMaximum;
|
|
|
+
|
|
|
public int numPoints;
|
|
|
|
|
|
public static final int MAX_NUM_ATTACKS = 20;
|
|
|
+
|
|
|
public static final float MAX_DISTANCE = 1000.0f; // 1km
|
|
|
|
|
|
public SSIDArea(LatLng initialLocation) {
|
|
@@ -166,16 +175,25 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
public boolean doesLocationBelongToArea(LatLng location) {
|
|
|
LatLng center = calculateCenterLocation();
|
|
|
float[] result = new float[1];
|
|
|
- Location.distanceBetween(center.latitude, center.longitude, location.latitude, location.longitude, result);
|
|
|
+ Location.distanceBetween(center.latitude, center.longitude, location.latitude,
|
|
|
+ location.longitude, result);
|
|
|
return result[0] < MAX_DISTANCE;
|
|
|
}
|
|
|
|
|
|
public void addLocation(LatLng location) {
|
|
|
Point point = new Point(location.latitude, location.longitude);
|
|
|
- if (point.x < mMinimum.x) mMinimum.x = point.x;
|
|
|
- if (point.x > mMaximum.x) mMaximum.x = point.x;
|
|
|
- if (point.y < mMinimum.y) mMinimum.y = point.y;
|
|
|
- if (point.y > mMaximum.y) mMaximum.y = point.y;
|
|
|
+ if (point.x < mMinimum.x) {
|
|
|
+ mMinimum.x = point.x;
|
|
|
+ }
|
|
|
+ if (point.x > mMaximum.x) {
|
|
|
+ mMaximum.x = point.x;
|
|
|
+ }
|
|
|
+ if (point.y < mMinimum.y) {
|
|
|
+ mMinimum.y = point.y;
|
|
|
+ }
|
|
|
+ if (point.y > mMaximum.y) {
|
|
|
+ mMaximum.y = point.y;
|
|
|
+ }
|
|
|
numPoints++;
|
|
|
}
|
|
|
|
|
@@ -191,74 +209,108 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
|
|
|
public int calculateColor() {
|
|
|
int threatLevel = numPoints;
|
|
|
- if (threatLevel > MAX_NUM_ATTACKS) threatLevel = MAX_NUM_ATTACKS;
|
|
|
- float alpha = 1.0f - (float)(threatLevel-1) / (float)(MAX_NUM_ATTACKS-1);
|
|
|
+ if (threatLevel > MAX_NUM_ATTACKS) {
|
|
|
+ threatLevel = MAX_NUM_ATTACKS;
|
|
|
+ }
|
|
|
+ float alpha = 1.0f - (float) (threatLevel - 1) / (float) (MAX_NUM_ATTACKS - 1);
|
|
|
return Color.argb(127, (int) (240.0 + 15.0 * alpha), (int) (80.0 + 175.0 * alpha), 60);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* fills the map with markers and circle representing SSIDs
|
|
|
+ * does it asynchronously in background thread
|
|
|
*/
|
|
|
private void populateMap() {
|
|
|
- sMap.clear();
|
|
|
-
|
|
|
- UglyDbHelper dbh = new UglyDbHelper(getActivity());
|
|
|
- ArrayList<Record> records = dbh.getRecordsForFilter(new LogFilter());
|
|
|
-
|
|
|
- HashMap<String, ArrayList<SSIDArea>> threadAreas = new HashMap<String, ArrayList<SSIDArea>>();
|
|
|
-
|
|
|
- for (Record record : records) {
|
|
|
- LatLng location = new LatLng(record.getLatitude(), record.getLongitude());
|
|
|
- Log.i("location", "lat: " + location.latitude + " long: " + location.longitude);
|
|
|
- ArrayList<SSIDArea> areas;
|
|
|
- if (threadAreas.containsKey(record.getSsid())) {
|
|
|
- areas = threadAreas.get(record.getSsid());
|
|
|
- boolean foundArea = false;
|
|
|
- for (SSIDArea area : areas) {
|
|
|
- if (area.doesLocationBelongToArea(location)) {
|
|
|
- area.addLocation(location);
|
|
|
- foundArea = true;
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (mLoader != null) {
|
|
|
+ mLoader.interrupt();
|
|
|
+ }
|
|
|
+ mLoader = new Thread(new Runnable() {
|
|
|
+ private void updateUI(final HashMap<String, ArrayList<SSIDArea>> threatAreas) {
|
|
|
+ if (mLoader.isInterrupted()) {
|
|
|
+ return;
|
|
|
}
|
|
|
- if (!foundArea) {
|
|
|
- areas.add(new SSIDArea(location));
|
|
|
+
|
|
|
+ Activity activity = getActivity();
|
|
|
+ if (activity != null) {
|
|
|
+ activity.runOnUiThread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ sMap.clear();
|
|
|
+
|
|
|
+ CircleOptions circleOptions = new CircleOptions().radius(200.0)
|
|
|
+ .fillColor(Color.argb(127, 240, 80, 60)).strokeWidth(0.0f);
|
|
|
+ BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory
|
|
|
+ .fromResource(R.drawable.wifi_marker);
|
|
|
+ for (Map.Entry<String, ArrayList<SSIDArea>> entry : threatAreas.entrySet()) {
|
|
|
+ String ssid = entry.getKey();
|
|
|
+ ArrayList<SSIDArea> areas = entry.getValue();
|
|
|
+
|
|
|
+ for (SSIDArea area : areas) {
|
|
|
+ int color = area.calculateColor();
|
|
|
+ LatLng center = area.calculateCenterLocation();
|
|
|
+ float radius = area.calculateRadius();
|
|
|
+
|
|
|
+ sMap.addCircle(circleOptions.center(center).radius(100.0 + radius)
|
|
|
+ .fillColor(color));
|
|
|
+ Marker marker = sMap.addMarker(new MarkerOptions()
|
|
|
+ .title(ssid + ": " + area.numPoints + (area.numPoints == 1
|
|
|
+ ? getResources()
|
|
|
+ .getString(R.string.attack)
|
|
|
+ : getResources().getString(R.string.attacks))).position(
|
|
|
+ center));
|
|
|
+ marker.setIcon(bitmapDescriptor);
|
|
|
+
|
|
|
+ sMarkerIDToSSID.put(marker.getId(), ssid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
- } else {
|
|
|
- areas = new ArrayList<SSIDArea>();
|
|
|
- areas.add(new SSIDArea(location));
|
|
|
- threadAreas.put(record.getSsid(), areas);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- CircleOptions circleOptions = new CircleOptions().radius(200.0).fillColor(Color.argb(127, 240, 80, 60)).strokeWidth(0.0f);
|
|
|
- BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.wifi_marker);
|
|
|
- for (Map.Entry<String, ArrayList<SSIDArea>> entry : threadAreas.entrySet()) {
|
|
|
- String ssid = entry.getKey();
|
|
|
- ArrayList<SSIDArea> areas = entry.getValue();
|
|
|
-
|
|
|
- for (SSIDArea area : areas) {
|
|
|
- int color = area.calculateColor();
|
|
|
- LatLng center = area.calculateCenterLocation();
|
|
|
- float radius = area.calculateRadius();
|
|
|
-
|
|
|
- sMap.addCircle(circleOptions.center(center).radius(100.0 + radius).fillColor(color));
|
|
|
- Marker marker = sMap.addMarker(new MarkerOptions()
|
|
|
- .title(ssid + ": " + area.numPoints + (area.numPoints == 1 ? getResources()
|
|
|
- .getString(R.string.attack)
|
|
|
- : getResources().getString(R.string.attacks))).position(
|
|
|
- center));
|
|
|
- marker.setIcon(bitmapDescriptor);
|
|
|
-
|
|
|
- sMarkerIDToSSID.put(marker.getId(), ssid);
|
|
|
+ private HashMap<String, ArrayList<SSIDArea>> doInBackground() {
|
|
|
+ UglyDbHelper dbh = new UglyDbHelper(getActivity());
|
|
|
+ ArrayList<Record> records = dbh.getRecordsForFilter(new LogFilter());
|
|
|
+
|
|
|
+ HashMap<String, ArrayList<SSIDArea>> threatAreas
|
|
|
+ = new HashMap<String, ArrayList<SSIDArea>>();
|
|
|
+
|
|
|
+ for (Record record : records) {
|
|
|
+ LatLng location = new LatLng(record.getLatitude(), record.getLongitude());
|
|
|
+ //Log.i("location", "lat: " + location.latitude + " long: " + location.longitude);
|
|
|
+ ArrayList<SSIDArea> areas;
|
|
|
+ if (threatAreas.containsKey(record.getSsid())) {
|
|
|
+ areas = threatAreas.get(record.getSsid());
|
|
|
+ boolean foundArea = false;
|
|
|
+ for (SSIDArea area : areas) {
|
|
|
+ if (area.doesLocationBelongToArea(location)) {
|
|
|
+ area.addLocation(location);
|
|
|
+ foundArea = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!foundArea) {
|
|
|
+ areas.add(new SSIDArea(location));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ areas = new ArrayList<SSIDArea>();
|
|
|
+ areas.add(new SSIDArea(location));
|
|
|
+ threatAreas.put(record.getSsid(), areas);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return threatAreas;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- sMap.setMyLocationEnabled(true);
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ updateUI(doInBackground());
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- LatLng tudarmstadt = new LatLng(49.86923, 8.6632768); // default location
|
|
|
- sMap.moveCamera(CameraUpdateFactory.newLatLngZoom(tudarmstadt, 13));
|
|
|
+ mLoader.start(); // run!
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -267,14 +319,14 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
* view must be removed if this object has been created once before
|
|
|
* that is why view is static
|
|
|
*
|
|
|
- * @param inflater the inflater
|
|
|
- * @param container the container
|
|
|
+ * @param inflater the inflater
|
|
|
+ * @param container the container
|
|
|
* @param savedInstanceState the savedInstanceState
|
|
|
* @return the view
|
|
|
*/
|
|
|
@Override
|
|
|
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
|
|
|
- Bundle savedInstanceState) {
|
|
|
+ Bundle savedInstanceState) {
|
|
|
super.onCreateView(inflater, container, savedInstanceState);
|
|
|
|
|
|
final Activity activity = getActivity();
|
|
@@ -284,10 +336,11 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
|
|
|
if (sView != null) {
|
|
|
ViewGroup parent = (ViewGroup) sView.getParent();
|
|
|
- if (parent != null)
|
|
|
+ if (parent != null) {
|
|
|
parent.removeView(sView);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
sView = inflater.inflate(R.layout.fragment_threatmap, container, false);
|
|
|
if (isGooglePlay()) {
|
|
@@ -301,7 +354,7 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
}
|
|
|
}
|
|
|
} catch (InflateException e) {
|
|
|
- // map already exists
|
|
|
+ // map already exists
|
|
|
//e.printStackTrace();
|
|
|
}
|
|
|
|
|
@@ -318,7 +371,8 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
public View getInfoContents(Marker marker) {
|
|
|
View view = inflater.inflate(R.layout.fragment_threatmap_infowindow, null);
|
|
|
if (view != null) {
|
|
|
- TextView titleTextView = (TextView)view.findViewById(R.id.threatmap_infowindow_title);
|
|
|
+ TextView titleTextView = (TextView) view
|
|
|
+ .findViewById(R.id.threatmap_infowindow_title);
|
|
|
if (titleTextView != null) {
|
|
|
titleTextView.setText(marker.getTitle());
|
|
|
}
|
|
@@ -327,6 +381,11 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ sMap.setMyLocationEnabled(true);
|
|
|
+
|
|
|
+ LatLng tudarmstadt = new LatLng(49.86923, 8.6632768); // default location
|
|
|
+ sMap.moveCamera(CameraUpdateFactory.newLatLngZoom(tudarmstadt, 13));
|
|
|
+
|
|
|
populateMap();
|
|
|
}
|
|
|
|
|
@@ -340,7 +399,8 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
public void onClick(DialogInterface dialog,
|
|
|
int which) {
|
|
|
}
|
|
|
- })
|
|
|
+ }
|
|
|
+ )
|
|
|
.setIcon(android.R.drawable.ic_dialog_info).show();
|
|
|
}
|
|
|
|
|
@@ -351,7 +411,8 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
|
public void onResume() {
|
|
|
super.onResume();
|
|
|
if (mLocationClient == null) {
|
|
|
- mLocationClient = new LocationClient(MainActivity.getInstance().getApplicationContext(), this, this);
|
|
|
+ mLocationClient = new LocationClient(MainActivity.getInstance().getApplicationContext(),
|
|
|
+ this, this);
|
|
|
}
|
|
|
mLocationClient.connect();
|
|
|
}
|