package com.oreilly.demo.android.pa.microjobs;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
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.OverlayItem;
/**
* MicroJobs
*/
public class MicroJobs extends MapActivity {
/**
* Application-wide log tag
*/
static final String LOG_TAG = "MicroJobs";
/**
* Database cursor to access user information
*/
private MicroJobsDatabase.WorkerCursor worker;
/**
* MJJobsOverlay
*/
private class MJJobsOverlay extends ItemizedOverlay<OverlayItem> {
/**
* @param marker the push-pin
*/
public MJJobsOverlay(Drawable marker) {
super(marker);
populate();
}
/**
* @see com.google.android.maps.ItemizedOverlay#size()
*/
@Override
public int size() {
int size = db.getJobsCount();
return size;
}
/**
* @see com.google.android.maps.ItemizedOverlay#createItem(int)
*/
@Override
protected OverlayItem createItem(int i) {
MicroJobsDatabase.JobDetailCursor c = db.getJobDetails(i+1);
startManagingCursor(c);
String contactName = c.getColContactName();
String description = c.getColDescription();
int lat = (int) c.getColLatitude();
int lon = (int) c.getColLongitude();
return new OverlayItem(new GeoPoint(lat, lon), contactName, description);
}
/**
* React to tap events on Map by showing an appropriate detail activity
*
* @see com.google.android.maps.ItemizedOverlay#onTap(com.google.android.maps.GeoPoint, com.google.android.maps.MapView)
*/
@Override
public boolean onTap(GeoPoint p, MapView mvMap1) {
long lat = p.getLatitudeE6();
long lon = p.getLongitudeE6();
long rowid = -1;
MicroJobsDatabase.JobsCursor c = db.getJobs(MicroJobsDatabase.JobsCursor.SortBy.title);
startManagingCursor(c);
startManagingCursor(c);
for( int i=0; i<c.getCount(); i++){
if ((Math.abs(c.getColLatitude()-lat)<1000) && (Math.abs(c.getColLongitude()-lon)<1000)){
rowid = c.getColJobsId();
break;
}
c.moveToNext();
}
if (0 > rowid) { return false; }
Bundle b = new Bundle();
b.putLong("_id", rowid);
Intent i = new Intent(MicroJobs.this, MicroJobsDetail.class);
i.putExtras(b);
startActivity(i);
return true;
}
}
MapView mvMap;
MicroJobsDatabase db;
MyLocationOverlay mMyLocationOverlay;
int latitude, longitude;
double[] curlocation = new double[2];
/**
* Called when the activity is first created.
*
* @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db = new MicroJobsDatabase(this);
getCurrentLocation((LocationManager) getSystemService(Context.LOCATION_SERVICE));
Spinner spnLocations = (Spinner) findViewById(R.id.spnLocations);
mvMap = (MapView) findViewById(R.id.mapmain);
// get the map controller
final MapController mc = mvMap.getController();
mMyLocationOverlay = new MyLocationOverlay(this, mvMap);
mMyLocationOverlay.enableMyLocation();
mMyLocationOverlay.runOnFirstFix(
new Runnable() {
@Override
public void run() {
mc.animateTo(mMyLocationOverlay.getMyLocation());
mc.setZoom(16);
updateCurLocation(mMyLocationOverlay.getMyLocation());
}
});
Drawable marker = getResources().getDrawable(R.drawable.android_tiny_image);
marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
mvMap.getOverlays().add(new MJJobsOverlay(marker));
mvMap.setClickable(true);
mvMap.setEnabled(true);
mvMap.setSatellite(false);
mvMap.setTraffic(false);
// start out with a general zoom
mc.setZoom(16);
mvMap.invalidate();
// Create a button click listener for the List Jobs button.
Button btnList = (Button) findViewById(R.id.btnShowList);
btnList.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MicroJobs.this.getApplication(), MicroJobsList.class);
startActivity(intent);
}
});
// Load a HashMap with locations and positions
List<String> lsLocations = new ArrayList<String>();
final HashMap<String, GeoPoint> hmLocations = new HashMap<String, GeoPoint>();
hmLocations.put("Current Location", new GeoPoint(latitude, longitude));
lsLocations.add("Current Location");
// Add favorite locations from this user's record in workers table
worker = db.getWorker();
hmLocations.put(worker.getColLoc1Name(), new GeoPoint((int)worker.getColLoc1Lat(), (int)worker.getColLoc1Long()));
lsLocations.add(worker.getColLoc1Name());
hmLocations.put(worker.getColLoc2Name(), new GeoPoint((int)worker.getColLoc2Lat(), (int)worker.getColLoc2Long()));
lsLocations.add(worker.getColLoc2Name());
hmLocations.put(worker.getColLoc3Name(), new GeoPoint((int)worker.getColLoc3Lat(), (int)worker.getColLoc3Long()));
lsLocations.add(worker.getColLoc3Name());
ArrayAdapter<String> aspnLocations
= new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, lsLocations);
aspnLocations.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnLocations.setAdapter(aspnLocations);
// Setup a callback for the spinner
spnLocations.setOnItemSelectedListener(
new OnItemSelectedListener() {
@Override
public void onNothingSelected(AdapterView<?> arg0) { }
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
TextView vt = (TextView) v;
if ("Current Location".equals(vt.getText())) {
mMyLocationOverlay.enableMyLocation();
try {
GeoPoint myLocation =
mMyLocationOverlay.getMyLocation();
if (myLocation != null) {
mc.animateTo(myLocation);
updateCurLocation(myLocation);
}
}
catch (Exception e) {
Log.i("MicroJobs", "Unable to animate map", e);
}
mvMap.invalidate();
} else {
mMyLocationOverlay.disableMyLocation();
mc.animateTo(hmLocations.get(vt.getText()));
updateCurLocation(hmLocations.get(vt.getText()));
}
mvMap.invalidate();
}
});
}
protected GeoPoint setCurrentGeoPoint(){
return mMyLocationOverlay.getMyLocation();
}
/**
* @see com.google.android.maps.MapActivity#onPause()
*/
@Override
public void onPause() {
super.onPause();
mMyLocationOverlay.disableMyLocation();
}
/**
* @see com.google.android.maps.MapActivity#onResume()
*/
@Override
public void onResume() {
super.onResume();
mMyLocationOverlay.enableMyLocation();
}
/**
* Setup menus for this page
*
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean supRetVal = super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, 0, Menu.NONE, getString(R.string.map_menu_zoom_in));
menu.add(Menu.NONE, 1, Menu.NONE, getString(R.string.map_menu_zoom_out));
menu.add(Menu.NONE, 2, Menu.NONE, getString(R.string.map_menu_set_satellite));
menu.add(Menu.NONE, 3, Menu.NONE, getString(R.string.map_menu_streetview));
menu.add(Menu.NONE, 4, Menu.NONE, getString(R.string.map_menu_set_traffic));
menu.add(Menu.NONE, 5, Menu.NONE, getString(R.string.map_menu_show_list));
return supRetVal;
}
/**
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
// Zoom in
zoomIn();
return true;
case 1:
// Zoom out
zoomOut();
return true;
case 2:
// Toggle satellite views
mvMap.setSatellite(!mvMap.isSatellite());
return true;
case 3:
// Launch StreetView with lat/lon of center of current map
String uri = "google.streetview:cbll="+curlocation[0]+","+curlocation[1]+"&cbp=1,0,,0,1.0&mz="+mvMap.getZoomLevel();
Intent streetView = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(streetView);
return true;
case 4:
// Toggle traffic views
mvMap.setTraffic(!mvMap.isTraffic());
return true;
case 5:
// Show the job list activity
startActivity(new Intent(MicroJobs.this, MicroJobsList.class));
return true;
}
return false;
}
/**
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP: // zoom in
zoomIn();
return true;
case KeyEvent.KEYCODE_DPAD_DOWN: // zoom out
zoomOut();
return true;
case KeyEvent.KEYCODE_BACK: // go back (meaning exit the app)
finish();
return true;
default:
return false;
}
}
/**
* Required method to indicate whether we display routes
*/
@Override
protected boolean isRouteDisplayed() { return false; }
/**
* Zoom in on the map
*/
private void zoomIn() {
mvMap.getController().setZoom(mvMap.getZoomLevel() + 1);
}
/**
* Zoom out on the map, but not past level 10
*/
private void zoomOut() {
int zoom = mvMap.getZoomLevel() - 1;
if (zoom < 5) { zoom = 5; }
mvMap.getController().setZoom(zoom);
}
/**
* @return the current location
*/
private Location getCurrentLocation(LocationManager lm) {
Location l = lm.getLastKnownLocation("gps");
if (null != l) { updateCurLocation(l); return l; }
// getLastKnownLocation returns null if loc provider is not enabled
l = new Location("gps");
l.setLatitude(42.352299);
l.setLatitude(-71.063979);
updateCurLocation(l);
return l;
}
/**
* updates curlocation for streetview use
*/
private void updateCurLocation(GeoPoint point) {
curlocation[0] = ((double) point.getLatitudeE6()) / ((double) 1E6);
curlocation[1] = ((double) point.getLongitudeE6()) / ((double) 1E6);
}
/**
* updates curlocation for streetview use
*/
private void updateCurLocation(Location loc) {
curlocation[0] = loc.getLatitude();
curlocation[1] = loc.getLongitude();
}
}