package com.showmehills;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.SQLException;
import android.graphics.Matrix;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationManager;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, IShowMeHillsActivity, SensorEventListener {
private GoogleMap mMap;
private HillDatabase myDbHelper;
private Location curLocation;
Marker compassMarker = null;
private RapidGPSLock mGPS;
private SensorManager mSensorManager;
Sensor accelerometer;
Sensor magnetometer;
float[] mGravity;
float[] mGeomagnetic;
float mDeclination = 0;
private boolean mHasAccurateGravity = false;
private boolean mHasAccurateAccelerometer = false;
Timer timer = new Timer();
private int GPSretryTime = 15;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_GAME);
mGPS = new RapidGPSLock(this);
mGPS.switchOn();
mGPS.findLocation();
myDbHelper = new HillDatabase(this, getString(R.string.dbname), getString(R.string.dbpath));
myDbHelper.createDataBase();
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
UpdateMarkers();
LatLng here = new LatLng(curLocation.getLatitude(), curLocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(here));
mMap.moveCamera(CameraUpdateFactory.zoomTo(10));
timer.scheduleAtFixedRate(new LocationTimerTask(), GPSretryTime * 1000, GPSretryTime * 1000);
}
public void UpdateMarkers()
{
if (mMap == null) return;
curLocation = mGPS.getCurrentLocation();
if (curLocation == null) return;
if (!myDbHelper.checkDataBase()) return;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String md = prefs.getString("distance", "25");
if (md.equals("")) md = "25";
int maxdistance = Integer.parseInt(md);
md = prefs.getString("mindistance", "0");
if (md.equals("")) md = "0";
int mindistance = Integer.parseInt(md);
md = prefs.getString("minheight", "0");
if (md.equals("")) md = "0";
int minheight = Integer.parseInt(md);
myDbHelper.SetDirections(curLocation, minheight, 9000, mindistance, (int)maxdistance);
LatLng pt = new LatLng(curLocation.getLatitude(), curLocation.getLongitude());
if (compassMarker == null) {
compassMarker = mMap.addMarker(new MarkerOptions().position(pt)
.anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.bluearrow)));
}
ArrayList<Hills> localhills = myDbHelper.localhills;
for (int h = 0; h < localhills.size(); h++)
{
Hills h1 = localhills.get(h);
Log.d("showmehills", "adding " + h1.hillname);
pt = new LatLng(h1.latitude, h1.longitude);
mMap.addMarker(new MarkerOptions().position(pt)
.title(h1.hillname)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.androidmarker)));
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu from XML resource
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mappreferences_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.preferences_menutitem) {
Intent settingsActivity = new Intent(getBaseContext(),AppPreferences.class);
startActivity(settingsActivity);
} else if (item.getItemId() == R.id.cameraview) {
finish();
} else if (item.getItemId() == R.id.help) {
Intent myHelpIntent = new Intent(getBaseContext(), Help.class);
startActivityForResult(myHelpIntent, 0);
} else if (item.getItemId() == R.id.about) {
Intent myAboutIntent = new Intent(getBaseContext(), About.class);
startActivityForResult(myAboutIntent, 0);
}
return super.onOptionsItemSelected(item);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
// some phones never set the sensormanager as reliable, even when readings are ok
// That means if we try to block it, those phones will never get a compass reading.
// So we let any readings through until we know we can get accurate readings. Once We know that
// we'll block the inaccurate ones
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER && mHasAccurateAccelerometer) return;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD && mHasAccurateGravity) return;
}
else
{
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) mHasAccurateAccelerometer = true;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mHasAccurateGravity = true;
}
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null) {
float[] rotationMatrixA = new float[9];
if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) {
Matrix tmpA = new Matrix();
tmpA.setValues(rotationMatrixA);
tmpA.postRotate( -mDeclination );
tmpA.getValues(rotationMatrixA);
float[] dv = new float[3];
SensorManager.getOrientation(rotationMatrixA, dv);
if (compassMarker != null)
{
compassMarker.setRotation( (float) Math.toDegrees(dv[0]));
}
}
}
}
public LocationManager GetLocationManager() {
return (LocationManager)getSystemService(Context.LOCATION_SERVICE);
}
class LocationTimerTask extends TimerTask
{
@Override
public void run()
{
Log.d("showmehills", "renew GPS search");
runOnUiThread(new Runnable() {
public void run() {
mGPS.RenewLocation();
}
});
}
}
@Override
protected void onResume() {
Log.d("showmehills", "onResume");
super.onResume();
mGPS.switchOn();
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_GAME);
timer = new Timer();
timer.scheduleAtFixedRate(new LocationTimerTask(),GPSretryTime* 1000,GPSretryTime* 1000);
UpdateMarkers();
myDbHelper.checkDataBase();
}
@Override
protected void onPause() {
Log.d("showmehills", "onPause");
super.onPause();
timer.cancel();
mGPS.switchOff();
mSensorManager.unregisterListener(this);
try {
myDbHelper.close();
}catch(SQLException sqle){
throw sqle;
}
}
@Override
protected void onStop()
{
try {
myDbHelper.close();
}catch(SQLException sqle){
throw sqle;
}
super.onStop();
}
}