|
@@ -31,11 +31,15 @@ import de.tudarmstadt.informatik.hostage.ui2.activity.MainActivity;
|
|
import static com.google.android.gms.common.GooglePlayServicesUtil.*;
|
|
import static com.google.android.gms.common.GooglePlayServicesUtil.*;
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * ThreatMapFragment
|
|
|
|
+ *
|
|
* Created by Fabio Arnold on 10.02.14.
|
|
* Created by Fabio Arnold on 10.02.14.
|
|
*/
|
|
*/
|
|
public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindowClickListener {
|
|
public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindowClickListener {
|
|
- private GoogleMap map = null;
|
|
|
|
- private static View view = null;
|
|
|
|
|
|
+ private GoogleMap mMap = null;
|
|
|
|
+ private static View sView = null;
|
|
|
|
+
|
|
|
|
+ private HashMap<String, String> mMarkerIDToSSID = new HashMap<String, String>();
|
|
|
|
|
|
/**
|
|
/**
|
|
* if google play services aren't available an error notification will be displayed
|
|
* if google play services aren't available an error notification will be displayed
|
|
@@ -51,12 +55,20 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * callback for when the info window of a marker gets clicked
|
|
|
|
+ * open the RecordOverviewFragment and display all records belonging to an SSID
|
|
|
|
+ *
|
|
|
|
+ * @param marker this info window belongs to
|
|
|
|
+ */
|
|
@Override
|
|
@Override
|
|
public void onInfoWindowClick(Marker marker) {
|
|
public void onInfoWindowClick(Marker marker) {
|
|
MainActivity.getInstance().displayView(MainActivity.MainMenuItem.RECORDS.getValue());
|
|
MainActivity.getInstance().displayView(MainActivity.MainMenuItem.RECORDS.getValue());
|
|
RecordOverviewFragment recordOverviewFragment = (RecordOverviewFragment)MainActivity.getInstance().getCurrentFragment();
|
|
RecordOverviewFragment recordOverviewFragment = (RecordOverviewFragment)MainActivity.getInstance().getCurrentFragment();
|
|
- recordOverviewFragment.showDetailsForSSID(marker.getId());
|
|
|
|
- Log.i("MARKER", ""+marker.getId());
|
|
|
|
|
|
+ if (recordOverviewFragment != null) {
|
|
|
|
+ String ssid = mMarkerIDToSSID.get(marker.getId());
|
|
|
|
+ recordOverviewFragment.showDetailsForSSID(ssid);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
private class Point {
|
|
private class Point {
|
|
@@ -67,61 +79,114 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ 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) {
|
|
|
|
+ //mMinimum = new Point(360.0, 360.0);
|
|
|
|
+ //mMaximum = new Point(-360.0, -360.0);
|
|
|
|
+ mMinimum = new Point(initialLocation.latitude, initialLocation.longitude);
|
|
|
|
+ mMaximum = new Point(initialLocation.latitude, initialLocation.longitude);
|
|
|
|
+ numPoints = 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public boolean doesLocationBelongToArea(LatLng location) {
|
|
|
|
+ LatLng center = calculateCenterLocation();
|
|
|
|
+ float[] result = new float[1];
|
|
|
|
+ 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;
|
|
|
|
+ numPoints++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public LatLng calculateCenterLocation() {
|
|
|
|
+ return new LatLng(0.5 * (mMinimum.x + mMaximum.x), 0.5 * (mMinimum.y + mMaximum.y));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public float calculateRadius() {
|
|
|
|
+ float[] result = new float[1];
|
|
|
|
+ Location.distanceBetween(mMinimum.x, mMinimum.y, mMaximum.x, mMaximum.y, result);
|
|
|
|
+ return 0.5f * result[0];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+ return Color.argb(127, (int) (240.0 + 15.0 * alpha), (int) (80.0 + 175.0 * alpha), 60);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private void populateMap() {
|
|
private void populateMap() {
|
|
UglyDbHelper dbh = new UglyDbHelper(getActivity());
|
|
UglyDbHelper dbh = new UglyDbHelper(getActivity());
|
|
ArrayList<Record> records = dbh.getAllRecords();
|
|
ArrayList<Record> records = dbh.getAllRecords();
|
|
|
|
|
|
- HashMap<String, ArrayList<Point>> threatLocations = new HashMap<String, ArrayList<Point>>();
|
|
|
|
|
|
+ HashMap<String, ArrayList<SSIDArea>> threadAreas = new HashMap<String, ArrayList<SSIDArea>>();
|
|
|
|
|
|
for (Record record : records) {
|
|
for (Record record : records) {
|
|
|
|
+ Log.i("SSID", record.getSsid() + " bssid " + record.getBssid());
|
|
|
|
+
|
|
LatLng location = new LatLng(record.getLatitude(), record.getLongitude());
|
|
LatLng location = new LatLng(record.getLatitude(), record.getLongitude());
|
|
- ArrayList<Point> points;
|
|
|
|
- if (threatLocations.containsKey(record.getSsid())) {
|
|
|
|
- points = threatLocations.get(record.getSsid());
|
|
|
|
|
|
+ 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 (!foundArea) {
|
|
|
|
+ areas.add(new SSIDArea(location));
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
- points = new ArrayList<Point>();
|
|
|
|
- threatLocations.put(record.getSsid(), points);
|
|
|
|
|
|
+ areas = new ArrayList<SSIDArea>();
|
|
|
|
+ areas.add(new SSIDArea(location));
|
|
|
|
+ threadAreas.put(record.getSsid(), areas);
|
|
}
|
|
}
|
|
- points.add(new Point(location.latitude, location.longitude));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- final int maxNumAttacks = 20;
|
|
|
|
CircleOptions circleOptions = new CircleOptions().radius(200.0).fillColor(Color.argb(127, 240, 80, 60)).strokeWidth(0.0f);
|
|
CircleOptions circleOptions = new CircleOptions().radius(200.0).fillColor(Color.argb(127, 240, 80, 60)).strokeWidth(0.0f);
|
|
- for (Map.Entry<String, ArrayList<Point>> entry : threatLocations.entrySet()) {
|
|
|
|
|
|
+ for (Map.Entry<String, ArrayList<SSIDArea>> entry : threadAreas.entrySet()) {
|
|
String ssid = entry.getKey();
|
|
String ssid = entry.getKey();
|
|
- ArrayList<Point> points = entry.getValue();
|
|
|
|
-
|
|
|
|
- // color
|
|
|
|
- int threatLevel = points.size();
|
|
|
|
- if (threatLevel > maxNumAttacks) threatLevel = maxNumAttacks;
|
|
|
|
- float alpha = 1.0f - (float)(threatLevel-1) / (float)(maxNumAttacks-1);
|
|
|
|
- int color = Color.argb(127, (int) (240.0 + 15.0 * alpha), (int) (80.0 + 175.0 * alpha), 60);
|
|
|
|
-
|
|
|
|
- // radius
|
|
|
|
- Point minimum = new Point(360.0, 360.0), maximum = new Point(-360.0, -360.0);
|
|
|
|
- for (Point point : points) {
|
|
|
|
- if (point.x < minimum.x) minimum.x = point.x;
|
|
|
|
- if (point.x > maximum.x) maximum.x = point.x;
|
|
|
|
- if (point.y < minimum.y) minimum.y = point.y;
|
|
|
|
- if (point.y > maximum.y) maximum.y = point.y;
|
|
|
|
|
|
+ ArrayList<SSIDArea> areas = entry.getValue();
|
|
|
|
+
|
|
|
|
+ for (SSIDArea area : areas) {
|
|
|
|
+ int color = area.calculateColor();
|
|
|
|
+ LatLng center = area.calculateCenterLocation();
|
|
|
|
+ float radius = area.calculateRadius();
|
|
|
|
+
|
|
|
|
+ mMap.addCircle(circleOptions.center(center).radius(100.0 + radius).fillColor(color));
|
|
|
|
+ Marker marker = mMap.addMarker(new MarkerOptions()
|
|
|
|
+ .title(ssid + ": " + area.numPoints + (area.numPoints == 1 ? " attack"
|
|
|
|
+ : " attacks")).position(
|
|
|
|
+ center));
|
|
|
|
+
|
|
|
|
+ mMarkerIDToSSID.put(marker.getId(), ssid);
|
|
}
|
|
}
|
|
- LatLng center = new LatLng(0.5 * (minimum.x + maximum.x), 0.5 * (minimum.y + maximum.y));
|
|
|
|
- float[] result = new float[1];
|
|
|
|
- Location.distanceBetween(minimum.x, minimum.y, maximum.x, maximum.y, result);
|
|
|
|
- float radius = 0.5f * result[0];
|
|
|
|
- map.addCircle(circleOptions.center(center).radius(100.0 + radius).fillColor(color));
|
|
|
|
- map.addMarker(new MarkerOptions().title(ssid + ": " + points.size() + (points.size() == 1 ? " attack" : " attacks")).position(
|
|
|
|
- center));
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- map.setMyLocationEnabled(true);
|
|
|
|
- map.setOnInfoWindowClickListener(this);
|
|
|
|
|
|
+ mMap.setMyLocationEnabled(true);
|
|
|
|
+ mMap.setOnInfoWindowClickListener(this);
|
|
|
|
|
|
LatLng tudarmstadt = new LatLng(49.86923, 8.6632768);
|
|
LatLng tudarmstadt = new LatLng(49.86923, 8.6632768);
|
|
//LatLng mapCenter = new LatLng(41.889, -87.622);
|
|
//LatLng mapCenter = new LatLng(41.889, -87.622);
|
|
|
|
|
|
//Location myLocation = map.getMyLocation();
|
|
//Location myLocation = map.getMyLocation();
|
|
- map.moveCamera(CameraUpdateFactory.newLatLngZoom(tudarmstadt, 13));
|
|
|
|
|
|
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(tudarmstadt, 13));
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -129,16 +194,16 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
Bundle savedInstanceState) {
|
|
Bundle savedInstanceState) {
|
|
super.onCreateView(inflater, container, savedInstanceState);
|
|
super.onCreateView(inflater, container, savedInstanceState);
|
|
|
|
|
|
- if (view != null) {
|
|
|
|
- ViewGroup parent = (ViewGroup) view.getParent();
|
|
|
|
|
|
+ if (sView != null) {
|
|
|
|
+ ViewGroup parent = (ViewGroup) sView.getParent();
|
|
if (parent != null)
|
|
if (parent != null)
|
|
- parent.removeView(view);
|
|
|
|
|
|
+ parent.removeView(sView);
|
|
}
|
|
}
|
|
|
|
|
|
try {
|
|
try {
|
|
- view = inflater.inflate(R.layout.fragment_threatmap, container, false);
|
|
|
|
|
|
+ sView = inflater.inflate(R.layout.fragment_threatmap, container, false);
|
|
if (isGooglePlay()) {
|
|
if (isGooglePlay()) {
|
|
- map = ((MapFragment) getFragmentManager()
|
|
|
|
|
|
+ mMap = ((MapFragment) getFragmentManager()
|
|
.findFragmentById(R.id.threatmapfragment)).getMap();
|
|
.findFragmentById(R.id.threatmapfragment)).getMap();
|
|
populateMap();
|
|
populateMap();
|
|
}
|
|
}
|
|
@@ -147,6 +212,6 @@ public class ThreatMapFragment extends Fragment implements GoogleMap.OnInfoWindo
|
|
e.printStackTrace();
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
|
|
- return view;
|
|
|
|
|
|
+ return sView;
|
|
}
|
|
}
|
|
}
|
|
}
|