/* Copyright (C) 2012, Dirk Trossen, airs@dirk-trossen.de This program 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 as version 2.1 of the License. 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.airs.visualisations; import java.util.Calendar; import java.util.List; import java.util.Locale; import com.airs.AIRS_local; import com.airs.R; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.MyLocationOverlay; import com.google.android.maps.Overlay; import com.google.android.maps.OverlayItem; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.format.Time; import android.text.method.LinkMovementMethod; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageButton; import android.widget.TextView; /** * Activity to view the GI/VI sensors on a Google Map view * * @see MapViewerOverlay * @see MapViewerOverlayTrack */ public class MapViewerActivity extends MapActivity implements OnClickListener { // offset for full day timestamp private static final long FULL_DAY = 1000*60*60*24; // milliseconds per day private TextView mTitle; private TextView mTitle2; private MapView mapView; private Bundle bundle; private int number_values; private int zoomLevel; private List<Overlay> mapOverlays; private Drawable drawable; private MapViewerOverlay itemizedOverlay; private MyLocationOverlay ownLocation; private MapController mapController; private SharedPreferences settings; private Editor editor; private GeoPoint last_recorded_location; private boolean showTrack = true; private String Symbol; private SQLiteDatabase airs_storage; private long startTime, endTime; private Cursor values = null; private boolean FirstDrawn = true; /** Called when the activity is first created. * @param savedInstanceState a Bundle of the saved state, according to Android lifecycle model */ @Override public void onCreate(Bundle savedInstanceState) { String title; Intent intent = getIntent(); // Set up the window layout super.onCreate(savedInstanceState); // get preferences settings = PreferenceManager.getDefaultSharedPreferences(this); editor = settings.edit(); // now open database airs_storage = AIRS_local.airs_storage; if (airs_storage != null) { // get previous zoom level zoomLevel = settings.getInt("ZoomLevel", 15); // start time of measurement // get time of midnight Calendar cal = Calendar.getInstance(Locale.getDefault()); cal.set(Calendar.HOUR, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.AM_PM, Calendar.AM); startTime = cal.getTimeInMillis(); // timestamp of start of visualisation endTime = startTime + FULL_DAY; // end time // get activity parameters bundle = intent.getExtras(); Symbol = bundle.getString("com.airs.Symbol"); // get symbol // window title as feature requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.mapview); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); // get window title fields mTitle = (TextView) findViewById(R.id.title_left_text); mTitle2 = (TextView) findViewById(R.id.title_right_text); mTitle.setText(R.string.app_name); // set listener for buttons ImageButton button = (ImageButton)findViewById(R.id.mapview_my_location); button.setOnClickListener(this); button = (ImageButton)findViewById(R.id.mapview_last_location); button.setOnClickListener(this); // get and set title title = bundle.getString("com.airs.Title"); if (title != null) mTitle2.setText(title); else mTitle2.setText("Title"); // add zoom mapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); // get controller for map mapController = mapView.getController(); // set zoom level mapController.setZoom(zoomLevel); // create overlays mapOverlays = mapView.getOverlays(); drawable = this.getResources().getDrawable(R.drawable.pin); itemizedOverlay = new MapViewerOverlay(drawable, getApplicationContext()); // initiate own location overlay ownLocation = new MyLocationOverlay(getApplicationContext(), mapView); ownLocation.enableCompass(); ownLocation.enableMyLocation(); // now draw markers addOverlay(); } else finish(); } /** Called when the activity is destroyed. */ @Override public void onDestroy() { super.onDestroy(); // unregister location updates ownLocation.disableMyLocation(); // store current zoom level for later editor.putInt("ZoomLevel", mapView.getZoomLevel()); editor.commit(); } /** Called to check if route is being displayed in this map (required by Google Maps API). */ @Override protected boolean isRouteDisplayed() { return false; } /** Called when the configuration of the activity has changed. * @param newConfig new configuration after change */ @Override public void onConfigurationChanged(Configuration newConfig) { //ignore orientation change super.onConfigurationChanged(newConfig); } /** Called when a button has been clicked on by the user * @param v Reference to the {@link android.view.View} of the button */ public void onClick(View v) { GeoPoint ownPoint; // dispatch depending on button pressed switch(v.getId()) { case R.id.mapview_my_location: ownPoint = ownLocation.getMyLocation(); if (ownPoint != null) mapController.animateTo(ownPoint); break; case R.id.mapview_last_location: mapController.animateTo(last_recorded_location); // then centre map at it and use different marker pin! break; } } /** Called when the Options menu is opened * @param menu Reference to the {@link android.view.Menu} */ @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuInflater inflater; menu.clear(); inflater = getMenuInflater(); inflater.inflate(R.menu.options_map, menu); return true; } /** Called when an option menu item has been selected by the user * @param item Reference to the {@link android.view.MenuItem} clicked on */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.main_about: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.AIRS_Map)) .setMessage(getString(R.string.MapAbout)) .setIcon(R.drawable.about) .setNeutralButton(getString(R.string.OK), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); // Make the textview clickable. Must be called after show() ((TextView)alert.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); return true; case R.id.map_mapview: mapView.setSatellite(false); return true; case R.id.map_satview: mapView.setSatellite(true); return true; case R.id.map_path: if (showTrack == true) showTrack = false; else showTrack = true; // remove overlay mapOverlays.clear(); // not first draw anymore FirstDrawn = false; // add overlay back addOverlay(); mapView.postInvalidate(); break; } return false; } private void addOverlay() { int i, j=0; GeoPoint point, last = new GeoPoint(0, 0); OverlayItem overlayitem = null; Time timeStamp = new Time(); int t_column, v_column; double longitude, latitude; double altitude; double temp_c, temp_f, humidity; String condition, wind; String query; String value; // issue query to the database if (values ==null) { query = new String("SELECT Timestamp, Value from 'airs_values' WHERE Timestamp BETWEEN " + String.valueOf(startTime) + " AND " + String.valueOf(endTime) + " AND Symbol='" + Symbol + "'"); values = airs_storage.rawQuery(query, null); } if (values == null) finish(); // get column index for timestamp and value t_column = values.getColumnIndex("Timestamp"); v_column = values.getColumnIndex("Value"); if (t_column == -1 || v_column == -1) finish(); number_values = values.getCount(); // are there any values? if (number_values != 0) { // move to first row to start values.moveToFirst(); // now draw markers for (i=0;i<number_values;i++) { // get timestamp for time measured timeStamp.set(values.getLong(t_column)); // get value value = values.getString(v_column); // create geo point String [] tokens = value.split(":"); if (Symbol.compareTo("GI") == 0) { // read tokens in values longitude = Double.parseDouble(tokens[0].trim()); latitude = Double.parseDouble(tokens[1].trim()); altitude = Double.parseDouble(tokens[2].trim()); point = new GeoPoint((int)(latitude * 1e6), (int)(longitude *1e6)); if (FirstDrawn == true) overlayitem = new OverlayItem(point, timeStamp.format("%H:%M:%S on %d.%m.%Y"), "Altitude: " + String.valueOf((int)altitude) + " m"); } else { latitude = Double.parseDouble(tokens[0].trim()); longitude = Double.parseDouble(tokens[1].trim()); temp_c = Double.parseDouble(tokens[2].trim()); temp_f = Double.parseDouble(tokens[3].trim()); humidity = Double.parseDouble(tokens[4].trim()); condition = tokens[5]; wind = tokens[6]; point = new GeoPoint((int)(latitude * 1e6), (int)(longitude *1e6)); if (FirstDrawn == true) overlayitem = new OverlayItem(point, timeStamp.format("%H:%M:%S on %d.%m.%Y"), "Conditions:\nTemperature: " + String.valueOf(temp_c) + " C (" + String.valueOf(temp_f) + " F)\nHumidity: " + String.valueOf(humidity) + "%\nConditions: " + condition + "\nWind: " + wind); } if (j == 0) last = point; // count the actually shown points j++; // is this the last element? if (i==number_values-1) { last_recorded_location = point; // save point for later in case button is pressed if (FirstDrawn == true) mapController.animateTo(point); // then centre map at it and use different marker pin! if (FirstDrawn == true) itemizedOverlay.addOverlay(overlayitem, this.getResources().getDrawable(R.drawable.current_pin)); } else // add overlay item to list with default marker if (FirstDrawn == true) itemizedOverlay.addOverlay(overlayitem); // shall I add the track? if (showTrack == true) { mapOverlays.add(new MapViewerOverlayTrack(last, point)); last = point; } // dereference for garbage collector point = null; overlayitem = null; // now move to next row values.moveToNext(); } // close resources values.close(); values = null; // now add overlay to picture mapOverlays.add(itemizedOverlay); // add own location mapOverlays.add(ownLocation); } // finish if there's no value to be shown if (j==0) finish(); } }