/** * Filename: MapViewActivity.java (in org.repin.android.ui) * This file is part of the Redpin project. * * Redpin is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * any later version. * * Redpin 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Redpin. If not, see <http://www.gnu.org/licenses/>. * * (c) Copyright ETH Zurich, Pascal Brogle, Philipp Bolliger, 2010, ALL RIGHTS RESERVED. * * www.redpin.org */ package org.redpin.android.ui; import org.redpin.android.ApplicationContext; import org.redpin.android.R; import org.redpin.android.core.Fingerprint; import org.redpin.android.core.Location; import org.redpin.android.core.Map; import org.redpin.android.core.Measurement; import org.redpin.android.core.Vector; import org.redpin.android.core.measure.WiFiReading; import org.redpin.android.net.InternetConnectionManager; import org.redpin.android.net.Response; import org.redpin.android.net.SynchronizationManager; import org.redpin.android.net.home.FingerprintRemoteHome; import org.redpin.android.net.home.LocationRemoteHome; import org.redpin.android.net.home.RemoteEntityHomeCallback; import org.redpin.android.net.wifi.WifiSniffer; import org.redpin.android.ui.list.MainListActivity; import org.redpin.android.ui.list.SearchListActivity; import org.redpin.android.ui.mapview.MapView; import org.redpin.android.util.ExceptionReporter; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; /** * Main activity of the client that displays maps and locations * * @author Pascal Brogle (broglep@student.ethz.ch) * */ public class MapViewActivity extends Activity { private static final String TAG = MapViewActivity.class.getSimpleName(); MapView mapView; ImageButton locateButton; ImageButton addLocationButton; TextView mapName; ProgressDialog progressDialog; WifiSniffer mWifiService; Location mLocation; WiFiReading wfreading, wfreading2, wfreading3; Vector<WiFiReading> vectorWifi; Measurement measurement; private RelativeLayout mapTopBar; /** * {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ApplicationContext.init(getApplicationContext()); ExceptionReporter.register(this); registerReceiver(connectionChangeReceiver, new IntentFilter( InternetConnectionManager.CONNECTIVITY_ACTION)); startService(new Intent(MapViewActivity.this, SynchronizationManager.class)); bindService(new Intent(this, InternetConnectionManager.class), mICMConnection, Context.BIND_AUTO_CREATE); /* * startService(new Intent(MapViewActivity.this, * InternetConnectionManager.class)); */ startWifiSniffer(); /* * bindService(new Intent(this, WifiSniffer.class), mWifiConnection, * Context.BIND_AUTO_CREATE); registerReceiver(wifiReceiver, new * IntentFilter( WifiSniffer.WIFI_ACTION)); */ setContentView(R.layout.map_view); mapView = (MapView) findViewById(R.id.map_view_component); mapName = (TextView) findViewById(R.id.map_name); mapTopBar = (RelativeLayout) findViewById(R.id.map_topbar); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { mapTopBar.setVisibility(View.GONE); } addLocationButton = (ImageButton) findViewById(R.id.add_location_button); addLocationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addNewLocation(); } }); locateButton = (ImageButton) findViewById(R.id.locate_button); locateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { locate(); } }); progressDialog = new ProgressDialog(this); // progressDialog.setCancelable(false); progressDialog.setCancelable(true); progressDialog.setIndeterminate(true); progressDialog.setMessage(getText(R.string.taking_measurement)); setOnlineMode(false); restoreState(); show(); } /** * Starts the setting screen * * @param target {@link View} that called this method */ public void button_Settings(View target) { Intent intent = new Intent(this, SettingsActivity.class); startActivity(intent); } private static final String pref_url = "url"; private static final String pref_scrollX = "x"; private static final String pref_scrollY = "y"; /** * Saves some of the {@link MapView} state */ private void saveState() { SharedPreferences preferences = getPreferences(MODE_PRIVATE); Editor edit = preferences.edit(); edit.putString(pref_url, mapView.getUrl()); int[] scroll = mapView.getScrollXY(); edit.putInt(pref_scrollX, scroll[0]); edit.putInt(pref_scrollY, scroll[1]); edit.commit(); } /** * Restores the {@link MapView} to show the last shown map */ private void restoreState() { SharedPreferences preferences = getPreferences(MODE_PRIVATE); String mapUrl = preferences.getString(pref_url, null); int scrollX = preferences.getInt(pref_scrollX, 0); int scrollY = preferences.getInt(pref_scrollY, 0); if (getIntent().getData() == null && mapUrl != null) { getIntent().setData(Uri.parse(mapUrl)); preferences.edit().clear().commit(); mapView.requestScroll(scrollX, scrollY, true); } preferences.edit().clear().commit(); } /** * {@inheritDoc} */ @Override protected void onDestroy() { saveState(); unregisterReceiver(connectionChangeReceiver); stopWifiSniffer(); stopService(new Intent(MapViewActivity.this, SynchronizationManager.class)); /* * stopService(new Intent(MapViewActivity.this, * InternetConnectionManager.class)); */ unbindService(mICMConnection); super.onDestroy(); } /** * Shows the {@link MapView} */ protected void show() { getIntent().resolveType(this); mapView.show(getIntent().getData()); Map m = mapView.getCurrentMap(); if (m != null) { mapName.setText(m.getMapName()); } } /** * Displays the current location on the map * @param loc The current estimated location */ protected void showLocation(Location loc) { if (loc == null) return; Map m = (Map) loc.getMap(); if (m != null) { mapName.setText(m.getMapName()); } mapView.showLocation(loc, true); } /** * {@inheritDoc} */ @Override protected void onNewIntent(Intent intent) { setIntent(intent); show(); } /** * Initiates a scan for a new measurement, creates a location and afterwards displays it on the map */ private void addNewLocation() { Map currentMap = mapView.getCurrentMap(); if (currentMap == null) { new AlertDialog.Builder(this).setPositiveButton( android.R.string.ok, null) .setTitle(R.string.map_view_title).setMessage( R.string.map_view_no_map_selected).create().show(); Log.w(TAG, "addNewLocation: no current map shown"); return; } progressDialog.show(); Location location = new Location(); location.setMap(currentMap); firstMeasurement = true; mLocation = location; mWifiService.forceMeasurement(); } /** * Locates the client */ private void locate() { progressDialog.show(); mLocation = null; mWifiService.forceMeasurement(); } /** * Sets the connectivity mode of the view * * @param isOnline <code>True</code> if the client can connect to the server, <code>false</code> otherwise */ private void setOnlineMode(boolean isOnline) { mapView.setModifiable(isOnline); locateButton.setEnabled(isOnline); addLocationButton.setEnabled(true); } /** * Starts the sniffer and registers the receiver */ private void startWifiSniffer() { bindService(new Intent(this, WifiSniffer.class), mWifiConnection, Context.BIND_AUTO_CREATE); registerReceiver(wifiReceiver, new IntentFilter(WifiSniffer.WIFI_ACTION)); Log.i(TAG, "Started WifiSniffer"); } /** * Stops the sniffer and unregisters the receiver */ private void stopWifiSniffer() { if (mWifiService != null) { mWifiService.stopMeasuring(); } unbindService(mWifiConnection); unregisterReceiver(wifiReceiver); Log.i(TAG, "Stopped WifiSniffer"); } /** * {@link InternetConnectionManager} {@link ServiceConnection} to check * current online state */ private ServiceConnection mICMConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { InternetConnectionManager mManager = ((InternetConnectionManager.LocalBinder) service) .getService(); setOnlineMode(mManager.isOnline()); } @Override public void onServiceDisconnected(ComponentName name) { } }; /** * Receives notifications about connectivity changes */ private BroadcastReceiver connectionChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { setOnlineMode(intent.getFlags() == InternetConnectionManager.ONLINE_FLAG); } }; private boolean firstMeasurement = false; /** * Receives notifications about new available measurements */ private BroadcastReceiver wifiReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Measurement m = mWifiService.retrieveLastMeasurement(); if (m == null) return; if (mLocation != null) { // Interval Scanning Fingerprint fp = new Fingerprint(mLocation, m); FingerprintRemoteHome.setFingerprint(fp, new RemoteEntityHomeCallback() { @Override public void onResponse(Response<?> response) { if (firstMeasurement) { progressDialog.hide(); mapView.addNewLocation(mLocation); firstMeasurement = false; } Log .i(TAG, "addNewLocation: setFingerprint successfull"); } @Override public void onFailure(Response<?> response) { progressDialog.hide(); Log.i(TAG, "addNewLocation: setFingerprint failed: " + response.getStatus() + ", " + response.getMessage()); } }); } else { // Localization LocationRemoteHome.getLocation(m, new RemoteEntityHomeCallback() { @Override public void onFailure(Response<?> response) { progressDialog.hide(); new AlertDialog.Builder(MapViewActivity.this).setMessage(response.getMessage()).setPositiveButton(android.R.string.ok, null).create().show(); } @Override public void onResponse(Response<?> response) { progressDialog.hide(); Location l = (Location) response.getData(); showLocation(l); } }); mWifiService.stopMeasuring(); } } }; /** * {@link ServiceConnection} for the {@link WifiSniffer} */ private ServiceConnection mWifiConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { mWifiService = ((WifiSniffer.LocalBinder) service).getService(); } @Override public void onServiceDisconnected(ComponentName name) { mWifiService = null; } }; /** * {@inheritDoc} */ @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, R.id.options_menu_search, 0, R.string.options_menu_search_text).setIcon( R.drawable.menu_search); menu.add(0, R.id.options_menu_listview, 0, R.string.options_menu_listview_text).setIcon( R.drawable.menu_list_black); menu.add(0, R.id.options_menu_add_map, 0, R.string.options_menu_add_map_text).setIcon( R.drawable.menu_addmap_black); return true; } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.options_menu_add_map: Intent newmap = new Intent(this, NewMapActivity.class); startActivity(newmap); return true; case R.id.options_menu_listview: Intent mainlist = new Intent(this, MainListActivity.class); startActivity(mainlist); return true; case R.id.options_menu_search: Intent search = new Intent(this, SearchListActivity.class); startActivity(search); return true; } return false; } /** * {@inheritDoc} */ @Override public boolean onSearchRequested() { Intent search = new Intent(this, SearchListActivity.class); startActivity(search); return false; } }