diff --git a/app/build.properties b/app/build.properties
index a2b05823b..df9cfe4c1 100644
--- a/app/build.properties
+++ b/app/build.properties
@@ -1,7 +1,7 @@
#Build Properties
-#Sat Nov 24 09:14:14 EST 2018
+#Wed Jan 02 20:18:46 CST 2019
version_minor=0
-version_build=0
+version_build=4
version_patch=3
version_store=44
version_major=2
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 07ba62b9c..0794c2479 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -23,6 +23,8 @@
+
+
= Build.VERSION_CODES.M) {
if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
- activity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
+ activity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED||
+ activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED ||
+ activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
return;
}
if (activity.isFinishing()) {
return;
}
activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
+ activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
}
}
diff --git a/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationGroup.java b/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationGroup.java
index 940274cf0..7ba45ac49 100644
--- a/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationGroup.java
+++ b/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationGroup.java
@@ -26,8 +26,8 @@
import java.util.List;
public enum NavigationGroup {
- GROUP_FEATURE(NavigationMenu.ACCESS_POINTS, NavigationMenu.CHANNEL_RATING, NavigationMenu.CHANNEL_GRAPH, NavigationMenu.TIME_GRAPH),
- GROUP_OTHER(NavigationMenu.EXPORT, NavigationMenu.CHANNEL_AVAILABLE, NavigationMenu.VENDORS),
+ GROUP_FEATURE(NavigationMenu.ACCESS_POINTS),
+ GROUP_OTHER(NavigationMenu.SET_DESTINATION, NavigationMenu.COLLECT_DATA),
GROUP_SETTINGS(NavigationMenu.SETTINGS, NavigationMenu.ABOUT);
private final List navigationMenus;
diff --git a/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationMenu.java b/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationMenu.java
index 82b7ca268..3f4bc23e6 100644
--- a/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationMenu.java
+++ b/app/src/main/java/com/vrem/wifianalyzer/navigation/NavigationMenu.java
@@ -35,12 +35,8 @@
public enum NavigationMenu {
ACCESS_POINTS(R.drawable.ic_network_wifi_grey_500_48dp, R.string.action_access_points, NavigationItemFactory.ACCESS_POINTS, NavigationOptionFactory.AP),
- CHANNEL_RATING(R.drawable.ic_wifi_tethering_grey_500_48dp, R.string.action_channel_rating, NavigationItemFactory.CHANNEL_RATING, NavigationOptionFactory.RATING),
- CHANNEL_GRAPH(R.drawable.ic_insert_chart_grey_500_48dp, R.string.action_channel_graph, NavigationItemFactory.CHANNEL_GRAPH, NavigationOptionFactory.OTHER),
- TIME_GRAPH(R.drawable.ic_show_chart_grey_500_48dp, R.string.action_time_graph, NavigationItemFactory.TIME_GRAPH, NavigationOptionFactory.OTHER),
- EXPORT(R.drawable.ic_import_export_grey_500_48dp, R.string.action_export, NavigationItemFactory.EXPORT),
- CHANNEL_AVAILABLE(R.drawable.ic_location_on_grey_500_48dp, R.string.action_channel_available, NavigationItemFactory.CHANNEL_AVAILABLE),
- VENDORS(R.drawable.ic_list_grey_500_48dp, R.string.action_vendors, NavigationItemFactory.VENDORS),
+ SET_DESTINATION(R.drawable.ic_wifi_tethering_grey_500_48dp, R.string.set_destination, NavigationItemFactory.SET_DESTINATION, NavigationOptionFactory.OTHER),
+ COLLECT_DATA(R.drawable.ic_show_chart_grey_500_48dp, R.string.collect_data, NavigationItemFactory.COLLECT_DATA, NavigationOptionFactory.OTHER),
SETTINGS(R.drawable.ic_settings_grey_500_48dp, R.string.action_settings, NavigationItemFactory.SETTINGS),
ABOUT(R.drawable.ic_info_outline_grey_500_48dp, R.string.action_about, NavigationItemFactory.ABOUT);
diff --git a/app/src/main/java/com/vrem/wifianalyzer/navigation/items/NavigationItemFactory.java b/app/src/main/java/com/vrem/wifianalyzer/navigation/items/NavigationItemFactory.java
index 49bdc1310..828a9e8b1 100644
--- a/app/src/main/java/com/vrem/wifianalyzer/navigation/items/NavigationItemFactory.java
+++ b/app/src/main/java/com/vrem/wifianalyzer/navigation/items/NavigationItemFactory.java
@@ -22,21 +22,14 @@
import com.vrem.wifianalyzer.about.AboutFragment;
import com.vrem.wifianalyzer.settings.SettingsFragment;
-import com.vrem.wifianalyzer.vendor.VendorFragment;
import com.vrem.wifianalyzer.wifi.accesspoint.AccessPointsFragment;
-import com.vrem.wifianalyzer.wifi.channelavailable.ChannelAvailableFragment;
-import com.vrem.wifianalyzer.wifi.channelgraph.ChannelGraphFragment;
-import com.vrem.wifianalyzer.wifi.channelrating.ChannelRatingFragment;
-import com.vrem.wifianalyzer.wifi.timegraph.TimeGraphFragment;
+import com.vrem.wifianalyzer.wifi.collectdata.CollectDataFragment;
+import com.vrem.wifianalyzer.wifi.setdestination.SetTheDestinationFragment;
public class NavigationItemFactory {
public static final NavigationItem ACCESS_POINTS = new FragmentItem(new AccessPointsFragment());
- public static final NavigationItem CHANNEL_RATING = new FragmentItem(new ChannelRatingFragment());
- public static final NavigationItem CHANNEL_GRAPH = new FragmentItem(new ChannelGraphFragment());
- public static final NavigationItem TIME_GRAPH = new FragmentItem(new TimeGraphFragment());
- public static final NavigationItem EXPORT = new ExportItem();
- public static final NavigationItem CHANNEL_AVAILABLE = new FragmentItem(new ChannelAvailableFragment(), false);
- public static final NavigationItem VENDORS = new FragmentItem(new VendorFragment(), false, View.GONE);
+ public static final NavigationItem SET_DESTINATION = new FragmentItem(new SetTheDestinationFragment());
+ public static final NavigationItem COLLECT_DATA = new FragmentItem(new CollectDataFragment());
public static final NavigationItem SETTINGS = new FragmentItem(new SettingsFragment(), false, View.GONE);
public static final NavigationItem ABOUT = new FragmentItem(new AboutFragment(), false, View.GONE);
diff --git a/app/src/main/java/com/vrem/wifianalyzer/wifi/collectdata/CollectDataFragment.java b/app/src/main/java/com/vrem/wifianalyzer/wifi/collectdata/CollectDataFragment.java
new file mode 100644
index 000000000..e823bf627
--- /dev/null
+++ b/app/src/main/java/com/vrem/wifianalyzer/wifi/collectdata/CollectDataFragment.java
@@ -0,0 +1,142 @@
+package com.vrem.wifianalyzer.wifi.collectdata;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Environment;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.vrem.wifianalyzer.MainContext;
+import com.vrem.wifianalyzer.R;
+import com.vrem.wifianalyzer.settings.Settings;
+import com.vrem.wifianalyzer.wifi.band.WiFiBand;
+import com.vrem.wifianalyzer.wifi.model.SortBy;
+import com.vrem.wifianalyzer.wifi.model.WiFiData;
+import com.vrem.wifianalyzer.wifi.model.WiFiDetail;
+import com.vrem.wifianalyzer.wifi.predicate.WiFiBandPredicate;
+import com.vrem.wifianalyzer.wifi.scanner.UpdateNotifier;
+
+import org.apache.commons.collections4.Predicate;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+import static android.content.ContentValues.TAG;
+
+
+public class CollectDataFragment extends Fragment implements UpdateNotifier{
+
+ private Button saveBtn;
+ private EditText currentLocationEt;
+ private static String objectString = "";
+ private static JSONObject jsonObject=new JSONObject();
+
+
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View view = inflater.inflate(R.layout.collect_data, container, false);
+ MainContext.INSTANCE.getScannerService().register(this::update);
+
+ saveBtn = view.findViewById(R.id.saveCollectedData);
+ currentLocationEt = view.findViewById(R.id.collectDataEt);
+
+ // loop through wifiDetails and put() all bssid and current location
+ // call writeJSONtoFile with !!jsonObject!! IFF we really added any new values
+
+ saveBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ if (currentLocationEt.getText().toString().isEmpty())
+ try {
+ Log.d(TAG, "onClick: " + WiFiData.wiFiDetails.get(0).getBSSID()+" "+WiFiData.wiFiDetails.get(0).getTitle().split(" ")[0]);
+ jsonObject.put(WiFiData.wiFiDetails.get(0).getBSSID(),WiFiData.wiFiDetails.get(0).getTitle().split(" ")[0]);
+ writeJSONtoFile(MainContext.INSTANCE.getContext(), currentLocationEt.getText().toString(), jsonObject);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ /* readJSON(currentLocationEt.toString());*/
+ return view;
+ }
+
+
+ @Override
+ public void update(@NonNull WiFiData wiFiData) {
+
+ Settings settings = MainContext.INSTANCE.getSettings();
+ WiFiBand wiFiBand = settings.getWiFiBand();
+ Predicate predicate = new WiFiBandPredicate(wiFiBand);
+ WiFiData.wiFiDetails = wiFiData.getWiFiDetails(predicate, SortBy.STRENGTH);
+ }
+
+ private String readJSON(String filename) {
+ File directory = Environment.getExternalStorageDirectory();
+ File file = new File(directory + "/Notes/", filename);
+
+ StringBuilder text = new StringBuilder();
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(file));
+ String line;
+
+ while ((line = br.readLine()) != null) {
+
+ text.append(line);
+ text.append('\n');
+ }
+ JSONObject jsonObject = new JSONObject(String.valueOf(text));
+ for (int i = 0; i
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- */
-
package com.vrem.wifianalyzer.wifi.model;
+import android.content.Context;
+import android.os.Environment;
import android.support.annotation.NonNull;
+import android.util.Log;
+import android.widget.Toast;
+import com.vrem.util.FileUtils;
import com.vrem.wifianalyzer.MainContext;
+import com.vrem.wifianalyzer.R;
import com.vrem.wifianalyzer.vendor.model.VendorService;
import org.apache.commons.collections4.CollectionUtils;
@@ -28,18 +16,47 @@
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.lang3.builder.EqualsBuilder;
-
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+
+import static android.content.ContentValues.TAG;
+
public class WiFiData {
- public static final WiFiData EMPTY = new WiFiData(Collections.emptyList(), WiFiConnection.EMPTY, Collections.emptyList());
- private final List wiFiDetails;
- private final WiFiConnection wiFiConnection;
+ public static final WiFiData EMPTY = new WiFiData(Collections.emptyList(), WiFiConnection.EMPTY, Collections.emptyList());
+ public static String location = "";
+ public static List wiFiDetails;
private final List wiFiConfigurations;
+ private Context mContext = MainContext.INSTANCE.getContext();
+ private final WiFiConnection wiFiConnection;
+ private static JSONObject wiFiLocations = new JSONObject();
+
+
+ static
+
+ {
+ try {
+
+ String content = FileUtils.readFile(MainContext.INSTANCE.getResources(), R.raw.shanghai);
+ wiFiLocations = new JSONObject(content);
+ Toast.makeText(MainContext.INSTANCE.getContext(), "Loaded locations with " + wiFiLocations.length() + " MAC -> location mappings", Toast.LENGTH_LONG).show();
+ } catch (Exception e) {
+ Toast.makeText(MainContext.INSTANCE.getContext(), "Failed to load locations", Toast.LENGTH_LONG).show();
+ }
+ }
+
+ private static String lastNotified = "";
public WiFiData(@NonNull List wiFiDetails, @NonNull WiFiConnection wiFiConnection, @NonNull List wiFiConfigurations) {
this.wiFiDetails = wiFiDetails;
@@ -65,6 +82,7 @@ public List getWiFiDetails(@NonNull Predicate predicate,
results = sortAndGroup(results, sortBy, groupBy);
}
Collections.sort(results, sortBy.comparator());
+ notifyLocation(results);
return results;
}
@@ -91,6 +109,47 @@ List sortAndGroup(@NonNull List wiFiDetails, @NonNull So
return results;
}
+
+ private void notifyLocation(List wifiDetails) {
+
+
+ if (wifiDetails.size() < 3) {
+ return;
+ }
+ try {
+ String lookupKey = (wifiDetails.get(0).getBSSID().toUpperCase()/*+" " + wifiDetails.get(0).getWiFiSignal().getStrength()+"\n"+wifiDetails.get(1).getBSSID().toUpperCase()+" " + wifiDetails.get(1).getWiFiSignal().getStrength()+"\n"+wifiDetails.get(2).getBSSID().toUpperCase()+" " + wifiDetails.get(2).getWiFiSignal().getStrength()*/);
+ Log.d(TAG, "Wifidata: " + lookupKey);
+ location = wiFiLocations.getString(lookupKey);
+ if (location == null) {
+ location = wiFiLocations.getString((wifiDetails.get(1).getBSSID() + " " + wifiDetails.get(0).getBSSID() + " " + wifiDetails.get(2).getBSSID()).toUpperCase());
+ }
+ if (location == null) {
+ location = wiFiLocations.getString((wifiDetails.get(0).getBSSID() + " " + wifiDetails.get(1).getBSSID()).toUpperCase());
+ }
+ if (location == null) {
+ location = wiFiLocations.getString((wifiDetails.get(1).getBSSID() + " " + wifiDetails.get(0).getBSSID()).toUpperCase());
+ }
+ if (location == null) {
+ location = wiFiLocations.getString(wifiDetails.get(0).getBSSID().toUpperCase());
+ }
+ if (location == null) {
+ location = wiFiLocations.getString(wifiDetails.get(1).getBSSID().toUpperCase());
+ }
+ if (location != null) {
+ if (!lastNotified.equals(location)) {
+ Log.d(TAG, "notifyLocation: "+location);
+ Log.d(TAG, "notifyLocation: "+lastNotified);
+ Toast.makeText(MainContext.INSTANCE.getContext(), "You are in " + location, Toast.LENGTH_LONG).show();
+ lastNotified = location;
+
+ }
+ } else {
+ //Toast.makeText(MainContext.INSTANCE.getContext(), "Nothing found " + lookupKey, Toast.LENGTH_SHORT).show();
+ }
+ } catch (Exception e) {
+ }
+ }
+
@NonNull
private List getWiFiDetails(@NonNull Predicate predicate) {
Collection selected = CollectionUtils.select(wiFiDetails, predicate);
@@ -125,9 +184,9 @@ private class ConnectionPredicate implements Predicate {
@Override
public boolean evaluate(WiFiDetail wiFiDetail) {
return new EqualsBuilder()
- .append(wiFiConnection.getSSID(), wiFiDetail.getSSID())
- .append(wiFiConnection.getBSSID(), wiFiDetail.getBSSID())
- .isEquals();
+ .append(wiFiConnection.getSSID(), wiFiDetail.getSSID())
+ .append(wiFiConnection.getBSSID(), wiFiDetail.getBSSID())
+ .isEquals();
}
}
@@ -152,4 +211,4 @@ public WiFiDetail transform(WiFiDetail input) {
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/vrem/wifianalyzer/wifi/setdestination/SetTheDestinationFragment.java b/app/src/main/java/com/vrem/wifianalyzer/wifi/setdestination/SetTheDestinationFragment.java
new file mode 100644
index 000000000..bb5e78041
--- /dev/null
+++ b/app/src/main/java/com/vrem/wifianalyzer/wifi/setdestination/SetTheDestinationFragment.java
@@ -0,0 +1,200 @@
+
+package com.vrem.wifianalyzer.wifi.setdestination;
+
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.media.RingtoneManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.vrem.wifianalyzer.MainContext;
+import com.vrem.wifianalyzer.R;
+import com.vrem.wifianalyzer.settings.Settings;
+import com.vrem.wifianalyzer.wifi.band.WiFiBand;
+import com.vrem.wifianalyzer.wifi.model.SortBy;
+import com.vrem.wifianalyzer.wifi.model.WiFiData;
+import com.vrem.wifianalyzer.wifi.model.WiFiDetail;
+import com.vrem.wifianalyzer.wifi.predicate.WiFiBandPredicate;
+import com.vrem.wifianalyzer.wifi.scanner.UpdateNotifier;
+
+import org.apache.commons.collections4.Predicate;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.content.ContentValues.TAG;
+
+
+public class SetTheDestinationFragment extends Fragment implements UpdateNotifier {
+
+
+ private List wiFiDetails;
+ private static TextView currentLocationTv;
+ private static String selectedDestination;
+ private static String lastNotified;
+ private SwipeRefreshLayout swipeRefreshLayout;
+
+ @Override
+ public void update(@NonNull WiFiData wiFiData) {
+ setCurrentStationView();
+ destinationHasBeenReached();
+ Settings settings = MainContext.INSTANCE.getSettings();
+ WiFiBand wiFiBand = settings.getWiFiBand();
+ Predicate predicate = new WiFiBandPredicate(wiFiBand);
+ wiFiDetails = wiFiData.getWiFiDetails(predicate, SortBy.STRENGTH);
+ }
+
+ private boolean destinationHasBeenReached() {
+ boolean arrived = false;
+ if (WiFiData.location.equals(selectedDestination)&&!WiFiData.location.equals(lastNotified)) {
+ headsUpNotification();
+ vibrate();
+ lastNotified = WiFiData.location;
+ arrived = true;
+ }
+ return arrived;
+}
+
+ private void setCurrentStationView() {
+ if (currentLocationTv == null) {
+ currentLocationTv.setText("Unknown");
+ } else {
+ currentLocationTv.setText(WiFiData.location);
+ }
+ }
+
+
+ private void vibrate() {
+ Vibrator v = (Vibrator) MainContext.INSTANCE.getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ long[] pattern = {0, 1000, 200};
+ v.vibrate(pattern,2);
+ Log.d(TAG, "vibrate: it is called");
+
+ }
+
+ private void headsUpNotification(){
+
+ Intent intent = new Intent(MainContext.INSTANCE.getContext(), SetTheDestinationFragment.class);
+ PendingIntent pi = PendingIntent.getActivity(MainContext.INSTANCE.getContext(), 0, intent, 0);
+ Notification.Builder builder = new Notification.Builder(MainContext.INSTANCE.getContext());
+
+ builder.setContentTitle(WiFiData.location.toString())
+ .setContentText("You have arrived your destinantion")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
+ .setContentIntent(pi)
+ .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
+ .setPriority(Notification.PRIORITY_MAX);
+
+ NotificationManager notificationManager = (NotificationManager) MainContext.INSTANCE.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(0, builder.build());
+
+ }
+
+
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+ View view = inflater.inflate(R.layout.set_destination, container, false);
+ MainContext.INSTANCE.getScannerService().register(this::update);
+
+ currentLocationTv = view.findViewById(R.id.collectDatatext);
+ selectedDestination = "";
+
+ Spinner spinner = view.findViewById(R.id.random_spinner);
+
+
+
+ // Initializing a String Array
+ String[] locations = new String[]{
+ "终点 - Destination",
+ "MERCURY_29E6",
+ "***",
+ "B8 conference room",
+ "B#8 Women\'s restroom",
+ "epwj0016",
+ "B8 Classroom Door A"
+ };
+
+
+ final List locationList = new ArrayList<>(Arrays.asList(locations));
+
+ // Initializing an ArrayAdapter
+ final ArrayAdapter spinnerArrayAdapter = new ArrayAdapter(MainContext.INSTANCE.getContext(),R.layout.spinner_item, locationList){
+ @Override
+ public boolean isEnabled(int position){
+ if(position == 0)
+ {
+ // Disable the first item from Spinner
+ // First item will be use for hint
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ @Override
+ public View getDropDownView(int position, View convertView,
+ ViewGroup parent) {
+ View view = super.getDropDownView(position, convertView, parent);
+ TextView tv = (TextView) view;
+ if(position == 0){
+ // Set the hint text color gray
+ tv.setTextColor(Color.GRAY);
+ }
+ else {
+ tv.setTextColor(Color.BLACK);
+ }
+ return view;
+ }
+ };
+ spinnerArrayAdapter.setDropDownViewResource(R.layout.spinner_item);
+ spinner.setAdapter(spinnerArrayAdapter);
+
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ selectedDestination = (String) parent.getItemAtPosition(position);
+
+ // If user change the default selection
+ // First item is disable and it is used for hint
+ if(position > 0){
+ // Notify the selected item text
+ Toast.makeText
+ (MainContext.INSTANCE.getContext(), "Selected : " + selectedDestination, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+
+ }
+ });
+
+ return view;
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_corner.xml b/app/src/main/res/drawable/rounded_corner.xml
new file mode 100644
index 000000000..763253c08
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_corner.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/collect_data.xml b/app/src/main/res/layout/collect_data.xml
new file mode 100644
index 000000000..aadd22c97
--- /dev/null
+++ b/app/src/main/res/layout/collect_data.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/set_destination.xml b/app/src/main/res/layout/set_destination.xml
new file mode 100644
index 000000000..068ba3130
--- /dev/null
+++ b/app/src/main/res/layout/set_destination.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/spinner_item.xml b/app/src/main/res/layout/spinner_item.xml
new file mode 100644
index 000000000..901037a28
--- /dev/null
+++ b/app/src/main/res/layout/spinner_item.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/raw/shanghai.json b/app/src/main/res/raw/shanghai.json
new file mode 100644
index 000000000..407216ca4
--- /dev/null
+++ b/app/src/main/res/raw/shanghai.json
@@ -0,0 +1,267 @@
+{
+ "1C:60:DE:FF:29:E6": "MERCURY_29E6",
+ "D0:76:E7:3B:20:C0": "***",
+ "C8:94:BB:3E:4D:19": "***",
+ "C4:CA:D9:09:E9:60": "ChinaNet",
+ "C4:CA:D9:09:E9:61": "ChinaNet-EDU",
+ "78:A3:51:3F:D0:70": "epwj0016",
+ "E0:3F:49:93:5C:DC": "B3#101 [AgoraSpace]",
+ "38:2C:4A:95:E8:34": "B8 lobby [Agora Space]",
+ "9C:3D:CF:74:8A:5B": "B8 lobby meeting room",
+ "9C:3D:CF:74:8A:5C": "B8 lobby meeting room",
+ "A0:48:1C:5C:E6:30": "B8 classroom",
+ "08:62:66:BE:4C:F8": "B8 conference room",
+ "08:62:66:BE:4C:FC": "B8 Classroom Door A",
+ "08:62:66:BE:4C:FC 08:62:66:BE:4C:F8 00:1C:58:41:C2:E0": "B#8 Door A",
+ "08:62:66:BE:4C:FC 08:62:66:BE:4C:F8": "B#8 Classroom Door A",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:FC 00:1C:58:41:C2:E0": "B#8 Door B",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:FC": "B#8 Door B",
+ "38:2C:4A:95:E8:30 38:2C:4A:95:E8:34 08:62:66:BE:4C:F8": "B#8 Piano small meeting room",
+ "9C:3D:CF:74:8A:5B 9C:3D:CF:74:8A:5C 38:2C:4A:95:E8:30": "B#8 Lobby meeting room",
+ "9C:3D:CF:74:8A:5B 9C:3D:CF:74:8A:5C": "B#8 Lobby meeting room",
+ "08:62:66:BE:4C:F8 38:2C:4A:95:E8:30 60:BB:0C:AF:6E:DA": "B#8 Coffee machine",
+ "08:62:66:BE:4C:F8 38:2C:4A:95:E8:30": "B#8 Coffee machine",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:FC A0:48:1C:5C:E6:30": "B#8 Aquarium",
+ "B0:48:7A:51:1D:04 08:62:66:BE:4C:F8 08:62:66:BD:00:20": "B#8 Painter office",
+ "08:B2:66:BD:00:20 B0:48:7A:51:1D:04 08:62:66:BD:00:24": "B#8 Relaxation room",
+ "08:B2:66:BD:00:20 B0:48:7A:51:1D:04": "B#8 Relaxation room",
+ "08:B2:66:BD:00:20": "B#8 Relaxation room",
+ "08:62:66:BD:00:20 08:62:66:BD:00:24 B0:48:7A:51:1D:04": "B#8 Conference room",
+ "08:62:66:BD:00:20 08:62:66:BD:00:24": "B#8 Conference room",
+ "08:62:66:BD:00:20": "B#8 Conference room",
+ "00:1C:58:41:C2:E0 9C:3D:CF:74:8A:5C 08:62:66:BE:4C:F8": "B#8 Photography room",
+ "00:1C:58:41:C2:E0 9C:3D:CF:74:8A:5C": "B#8 Photography room",
+ "BE:DD:C2:10:7A:49 08:62:66:BE:4C:F8 38:2C:4A:95:E8:30": "B#8 Photography room",
+ "BE:DD:C2:10:7A:49 08:62:66:BE:4C:F8": "B#8 Photography room",
+ "BE:DD:C2:10:7A:49": "B#8 Photography room",
+ "A0:48:1C:5C:E6:30 08:62:66:BE:4C:F8 08:62:66:BE:4C:FC": "B#8 Classroom printer",
+ "A0:48:1C:5C:E6:30 08:62:66:BE:4C:F8": "B#8 Classroom printer",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:F8 00:1C:58:41:C2:E0": "B#8 Dining table",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:F8": "B#8 Dining table",
+ "38:2C:4A:95:E8:30 38:2C:4A:95:E8:34": "B#8 Men's restroom",
+ "38:2C:4A:95:E8:30": "B#8 Women's restroom",
+ "9C:3D:CF:74:8A:5C 60:BB:0C:AF:6E:DA 08:62:66:BE:4C:F8": "B#8 Coffee machine",
+ "9C:3D:CF:74:8A:5C 60:BB:0C:AF:6E:DA": "B#8 Coffee machine",
+ "38:2C:4A:95:E8:30 08:62:66:BE:4C:F8 60:BB:0C:AF:6E:DA": "B#8 Dining table",
+ "38:2C:4A:95:E8:30 08:62:66:BE:4C:F8": "B#8 Dining table",
+ "08:62:66:BE:4C:F8 00:1C:58:41:C2:E0 38:2C:4A:95:E8:30": "B#8 Photography room",
+ "08:62:66:BE:4C:F8 00:1C:58:41:C2:E0": "B#8 Photography room",
+ "00:1C:58:41:C2:E0 08:62:66:BE:4C:F8 38:2C:4A:95:E8:30": "B#8 Server room",
+ "00:1C:58:41:C2:E0 08:62:66:BE:4C:F8": "B#8 Server room",
+ "00:1C:58:41:C2:E0": "B#8 Server room",
+ "08:62:66:BD:00:20 B0:48:7A:51:1D:04 08:62:66:BD:00:24": "B#8 Relaxation room",
+ "08:62:66:BD:00:20 B0:48:7A:51:1D:04": "B#8 Relaxation room",
+ "B0:48:7A:51:1D:04 08:62:66:BE:4C:F8 08:62:66:BE:4C:F8": "B#8 Painter office",
+ "B0:48:7A:51:1D:04 08:62:66:BE:4C:F8": "B#8 Painter office",
+ "B0:48:7A:51:1D:04": "B#8 Painter office",
+ "08:62:66:BE:4C:F8 00:1C:58:41:C2:E0 08:62:66:BE:4C:FC": "B#8 Dart room",
+ "38:2C:4A:95:E8:30 08:62:66:BE:4C:F8 9C:3D:CF:74:8A:5B": "B#8 Washing machine room",
+ "08:62:66:BE:4C:F8 08:62:66:BE:4C:FC A0:48:1C:5C:E6:30 00:1C:58:51:C2:E0": "B#8 Dart room",
+ "08:62:66:BE:4C:FC 00:1C:58:41:C2:E0 A0:48:1C:5C:E6:30": "B#8 Aquarium",
+ "00:1C:58:41:C2:E0 08:62:66:BE:4C:F8 BE:DD:C2:10:7A:49": "B#8 Server room",
+ "BE:DD:C2:10:7A:49 08:62:66:BE:4C:F8 00:1C:58:41:C2:E0": "B#8 Photography room",
+ "C8:3A:35:5F:7E:D1 D8:50:E6:EA:7C:F8 20:A6:80:84:FC:64": "B#8 Stairwell",
+ "C8:3A:35:5F:7E:D1 D8:50:E6:EA:7C:F8": "B#8 Stairwell",
+ "D8:50:E6:EA:7C:F8 20:A6:80:84:FC:64": "B#8 Stairwell",
+ "06:69:6C:0C:53:3E": "静安寺2号线",
+ "0A:69:6C:0C:53:3F": "静安寺2号线",
+ "0A:69:6C:0C:52:C3": "静安寺2号线",
+ "06:69:6C:0C:53:3F": "静安寺2号线",
+ "EA:69:6C:32:74:4F": "静安寺2号线",
+ "0A:69:6C:22:DB:75": "静安寺2号线",
+ "DA:69:6C:32:70:FE": "静安寺2号线",
+ "06:69:6C:22:DB:75": "静安寺2号线",
+ "06:69:6C:22:DB:74": "静安寺2号线",
+ "06:69:6C:0C:52:93": "静安寺2号线",
+ "0A:69:6C:0C:53:3E": "静安寺2号线",
+ "5A:69:6C:32:6F:D6": "静安寺2号线",
+ "50:68:0A:D5:4B:F6": "静安寺2号线",
+ "EA:69:6C:32:72:7F": "静安寺2号线",
+ "06:69:6C:0C:52:92": "静安寺2号线",
+ "0A:69:6C:0C:59:5E": "南京西路2号线 ",
+ "0A:69:6C:0C:59:2F": "南京西路2号线 ",
+ "0A:69:6C:0C:59:2E": "南京西路2号线 ",
+ "4A:69:6C:32:78:55": "南京西路2号线 ",
+ "06:69:6C:0C:59:5E": "南京西路2号线 ",
+ "06:69:6C:0C:59:2F": "南京西路2号线 ",
+ "06:69:6C:0C:59:2E": "南京西路2号线 ",
+ "6A:69:6C:32:73:97": "南京西路2号线 ",
+ "06:69:6C:0C:59:5F": "南京西路2号线 ",
+ "06:69:6C:0C:59:BB": "南京西路2号线 ",
+ "0A:69:6C:0C:59:5F": "南京西路2号线 ",
+ "0A:69:6C:42:25:29": "人民广场2号线",
+ "06:69:6C:42:25:29": "人民广场2号线",
+ "06:69:6C:0C:54:2B": "人民广场2号线",
+ "AA:69:6C:32:71:2B": "人民广场2号线",
+ "4A:69:6C:20:E9:95": "人民广场2号线",
+ "0A:69:6C:0C:54:2B": "人民广场2号线",
+ "8A:69:6C:20:E1:D9": "人民广场2号线",
+ "06:69:6C:0C:53:5F": "南京东路2号线",
+ "06:69:6C:0C:53:16": "南京东路2号线",
+ "0A:69:6C:0C:54:AB": "南京东路2号线",
+ "06:69:6C:0C:53:17": "南京东路2号线",
+ "06:69:6C:0C:54:AA": "南京东路2号线",
+ "06:69:6C:0C:54:AB": "南京东路2号线",
+ "0A:69:6C:0C:52:AB": "南京东路2号线",
+ "2A:69:6C:20:E8:13": "南京东路2号线",
+ "06:69:6C:0C:52:AB": "南京东路2号线",
+ "0A:69:6C:0C:53:5E": "南京东路2号线",
+ "0A:69:6C:0C:53:16": "南京东路2号线",
+ "0A:69:6C:0C:53:17": "南京东路2号线",
+ "0A:69:6C:0C:54:AA": "南京东路2号线",
+ "1A:69:6C:32:74:32": "南京东路2号线",
+ "06:69:6C:0C:53:5E": "南京东路2号线",
+ "0A:69:6C:0C:53:7F": "陆家嘴2号线",
+ "0A:69:6C:0C:58:3B": "东昌路2号线",
+ "06:69:6C:0C:58:3B": "东昌路2号线",
+ "06:69:6C:0C:5A:3F": "东昌路2号线",
+ "0A:69:6C:BB:23:1C": "世纪大道2号线",
+ "2A:69:6C:32:B1:D3": "世纪大道2号线",
+ "0A:69:6C:BB:23:1D": "世纪大道2号线",
+ "06:69:6C:BB:23:1D": "世纪大道2号线",
+ "06:69:6C:B9:81:04": "世纪大道2号线",
+ "CA:69:6C:32:B0:DD": "世纪大道2号线",
+ "DA:69:6C:32:B0:DE": "世纪大道2号线",
+ "0A:69:6C:B9:81:03": "世纪大道2号线",
+ "06:69:6C:0C:53:D3": "上海科技馆2号线",
+ "06:69:6C:0C:53:23": "上海科技馆2号线",
+ "0A:69:6C:0C:53:D3": "上海科技馆2号线",
+ "06:69:6C:0C:52:FE": "上海科技馆2号线",
+ "06:69:6C:0C:53:DF": "上海科技馆2号线",
+ "06:69:6C:0C:5A:C2": "世纪公园2号线",
+ "CA:69:6C:31:F3:8D": "花木路7号线",
+ "4A:69:6C:32:01:B5": "花木路7号线",
+ "06:14:4B:70:8F:A4": "花木路7号线",
+ "0A:14:4B:6D:16:BF": "花木路7号线",
+ "06:14:4B:70:8F:A3": "花木路7号线",
+ "0A:14:4B:6D:16:C0": "花木路7号线",
+ "BA:69:6C:31:F3:8C": "花木路7号线",
+ "06:14:4B:6D:16:BF": "花木路7号线",
+ "0A:14:4B:70:8F:84": "花木路7号线",
+ "06:14:4B:6D:16:C0": "花木路7号线",
+ "0A:14:4B:70:8F:83": "花木路7号线",
+ "0A:14:4B:6D:1D:AC": "花木路7号线",
+ "DA:69:6C:31:FE:AE": "花木路7号线",
+ "0A:14:4B:6D:1D:AB": "花木路7号线",
+ "5A:69:6C:32:01:B6": "花木路7号线",
+ "0A:14:4B:6D:14:A4": "花木路7号线",
+ "06:14:4B:70:8F:84": "花木路7号线",
+ "0A:14:4B:70:8F:A4": "花木路7号线",
+ "06:14:4B:70:8F:83": "花木路7号线",
+ "06:14:4B:6D:1D:AC": "花木路7号线",
+ "0A:14:4B:70:8F:A3": "花木路7号线",
+ "EA:69:6C:31:FE:AF": "花木路7号线",
+ "06:14:4B:6D:1D:AB": "花木路7号线",
+ "06:14:4B:6D:14:A4": "花木路7号线",
+ "06:14:4B:6D:14:A3": "花木路7号线",
+ "AA:69:6C:32:66:DB": "龙阳路7号线",
+ "AA:69:6C:32:63:BB": "龙阳路7号线",
+ "06:14:4B:6D:1D:83": "龙阳路7号线",
+ "0A:14:4B:6D:1D:84": "龙阳路7号线",
+ "06:14:4B:6D:1D:84": "龙阳路7号线",
+ "7A:69:6C:32:64:28": "龙阳路7号线",
+ "0A:14:4B:6D:1D:87": "龙阳路7号线",
+ "06:14:4B:6D:1D:87": "龙阳路7号线",
+ "0A:14:4B:6D:1D:88": "龙阳路7号线",
+ "8A:69:6C:32:64:29": "龙阳路7号线",
+ "06:14:4B:6D:1D:88": "龙阳路7号线",
+ "0A:14:4B:6D:1D:83": "龙阳路7号线",
+ "0A:14:4B:6D:1D:47": "龙阳路7号线",
+ "0A:14:4B:6D:1D:C7": "龙阳路7号线",
+ "06:14:4B:6D:1D:47": "龙阳路7号线",
+ "06:14:4B:6D:1D:C7": "龙阳路7号线",
+ "0A:14:4B:6D:1D:C8": "龙阳路7号线",
+ "0A:69:6C:20:DD:51": "龙阳路7号线",
+ "06:14:4B:70:8F:77": "龙阳路7号线",
+ "0A:14:4B:70:8F:78": "龙阳路7号线",
+ "06:14:4B:6D:1D:C8": "龙阳路7号线",
+ "06:14:4B:70:8F:78": "龙阳路7号线",
+ "0A:14:4B:70:8F:77": "龙阳路7号线",
+ "9A:69:6C:32:63:BA": "龙阳路7号线",
+ "14:9D:09:C3:AD:C8": "龙阳路7号线",
+ "06:14:4B:71:32:48": "昌平路7号线",
+ "0A:14:4B:71:32:47": "昌平路7号线",
+ "06:14:4B:71:31:83": "昌平路7号线",
+ "3A:69:6C:32:63:74": "昌平路7号线",
+ "B8:BC:1B:32:12:79": "昌平路7号线",
+ "06:14:4B:71:31:8C": "昌平路7号线",
+ "DA:69:6C:32:62:EE": "昌平路7号线",
+ "0A:14:4B:71:31:8C": "昌平路7号线",
+ "6A:69:6C:31:F4:27": "昌平路7号线",
+ "06:14:4B:71:31:EB": "昌平路7号线",
+ "06:14:4B:71:31:8B": "昌平路7号线",
+ "3A:69:6C:32:6B:A4": "昌平路7号线",
+ "CA:69:6C:32:62:ED": "昌平路7号线",
+ "06:14:4B:71:31:A8": "昌平路7号线",
+ "06:14:4B:71:31:84": "昌平路7号线",
+ "0A:14:4B:71:31:A8": "昌平路7号线",
+ "1A:69:6C:32:6A:72": "昌平路7号线",
+ "AA:69:6C:31:F4:EB": "昌平路7号线",
+ "06:14:4B:71:31:A7": "昌平路7号线",
+ "06:14:4B:71:32:47": "昌平路7号线",
+ "0A:14:4B:71:31:A7": "昌平路7号线",
+ "0A:14:4B:71:32:48": "昌平路7号线",
+ "06:14:4B:6D:12:68": "昌平路7号线",
+ "06:14:4B:71:31:87": "昌平路7号线",
+ "0A:14:4B:71:31:88": "昌平路7号线",
+ "0A:14:4B:6D:12:68": "昌平路7号线",
+ "BA:69:6C:32:72:AC": "昌平路7号线",
+ "06:14:4B:6D:12:67": "昌平路7号线",
+ "0A:14:4B:6D:12:67": "昌平路7号线",
+ "06:14:4B:71:31:88": "昌平路7号线",
+ "8A:69:6C:32:65:A9": "昌平路7号线",
+ "3A:69:6C:34:59:94": "岚皋路7号线",
+ "06:14:4B:6D:17:8B": "岚皋路7号线",
+ "0A:14:4B:6D:17:8C": "岚皋路7号线",
+ "06:14:4B:6D:17:8C": "岚皋路7号线",
+ "0A:14:4B:6D:16:C7": "岚皋路7号线",
+ "06:14:4B:6D:16:C7": "岚皋路7号线",
+ "0A:14:4B:6D:13:1F": "岚皋路7号线",
+ "0A:14:4B:6D:16:C8": "岚皋路7号线",
+ "06:14:4B:6D:13:1F": "岚皋路7号线",
+ "0A:14:4B:6D:13:20": "岚皋路7号线",
+ "06:14:4B:6D:13:20": "岚皋路7号线",
+ "0A:14:4B:71:32:50": "镇坪路7号线",
+ "06:14:4B:71:31:B8": "镇坪路7号线",
+ "06:14:4B:71:32:4F": "镇坪路7号线",
+ "0A:14:4B:71:31:B8": "镇坪路7号线",
+ "0A:14:4B:71:32:4F": "镇坪路7号线",
+ "06:14:4B:71:3A:34": "长寿路7号线",
+ "0A:14:4B:71:3A:34": "长寿路7号线",
+ "0A:69:6C:BB:0F:60": "静安寺7号线",
+ "06:69:6C:BB:0F:61": "静安寺7号线",
+ "06:14:4B:71:32:30": "静安寺7号线",
+ "2A:69:6C:31:FA:B3": "静安寺7号线",
+ "0A:14:4B:71:32:30": "静安寺7号线",
+ "DA:69:6C:32:01:3E": "静安寺7号线",
+ "8A:69:6C:31:F6:49": "静安寺7号线",
+ "06:14:4B:71:32:3F": "静安寺7号线",
+ "0A:14:4B:71:32:3F": "静安寺7号线",
+ "06:14:4B:71:32:40": "静安寺7号线",
+ "06:14:4B:71:2F:5C": "静安寺7号线",
+ "0A:14:4B:71:32:40": "静安寺7号线",
+ "0A:14:4B:71:2F:67": "静安寺7号线",
+ "0A:14:4B:71:2F:68": "静安寺7号线",
+ "06:14:4B:71:2F:67": "静安寺7号线",
+ "06:14:4B:71:2F:68": "静安寺7号线",
+ "0A:14:4B:71:2F:5B": "静安寺7号线",
+ "0A:14:4B:71:2F:5C": "静安寺7号线",
+ "06:14:4B:71:2F:5B": "静安寺7号线",
+ "06:14:4B:6D:15:6C": "行知路7号线 ",
+ "06:14:4B:6D:16:4F": "行知路7号线 ",
+ "0A:14:4B:6D:16:50": "行知路7号线 ",
+ "06:14:4B:6D:16:50": "行知路7号线 ",
+ "CA:69:6C:32:67:0D": "行知路7号线 ",
+ "0A:14:4B:6D:15:6B": "行知路7号线 ",
+ "06:14:4B:6D:15:6B": "行知路7号线 ",
+ "0A:14:4B:6D:15:6C": "行知路7号线 ",
+ "0A:14:4B:6D:16:4F": "行知路7号线 ",
+ "4A:69:6C:32:62:D5": "行知路7号线 ",
+ "06:14:4B:79:0A:28": "行知路7号线 ",
+ "06:14:4B:78:FF:97": "行知路7号线 ",
+ "06:14:4B:78:FF:98": "行知路7号线 ",
+ "1A:69:6C:32:72:42": "行知路7号线 ",
+ "0A:14:4B:6D:16:FB": "行知路7号线 ",
+ "0A:14:4B:6D:16:FC": "行知路7号线 ",
+ "06:14:4B:6D:16:FC": "行知路7号线 "
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 50c287b28..c967799a7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,7 +20,7 @@
"WiFiAnalyzer"
- "WiFiAnalyzer (open-source)"
+ "Houtan Project"
"VREM Software Development"
"Copyright \u00A9 2015 \u002D "
"https://vremsoftwaredevelopment.github.io/WiFiAnalyzer"
@@ -32,9 +32,12 @@
"Pause"
"Play"
+
"Access Points"
"Channel Rating"
+ Set The Destination
+ Collect Data
"Channel Graph"
"Time Graph"
"Export"