aboutsummaryrefslogtreecommitdiffstats
path: root/src/cgeo/geocaching/cgeonavigate.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgeo/geocaching/cgeonavigate.java')
-rw-r--r--src/cgeo/geocaching/cgeonavigate.java503
1 files changed, 503 insertions, 0 deletions
diff --git a/src/cgeo/geocaching/cgeonavigate.java b/src/cgeo/geocaching/cgeonavigate.java
new file mode 100644
index 0000000..65afa17
--- /dev/null
+++ b/src/cgeo/geocaching/cgeonavigate.java
@@ -0,0 +1,503 @@
+package cgeo.geocaching;
+
+import gnu.android.app.appmanualclient.*;
+
+import java.util.ArrayList;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PowerManager;
+import android.util.Log;
+import android.app.Activity;
+import android.view.Menu;
+import android.view.SubMenu;
+import android.view.MenuItem;
+import android.widget.TextView;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.view.View;
+import android.view.WindowManager;
+import java.util.HashMap;
+import java.util.Locale;
+
+
+public class cgeonavigate extends Activity {
+
+ public static ArrayList<cgCoord> coordinates = new ArrayList<cgCoord>();
+ private Resources res = null;
+ private cgeoapplication app = null;
+ private Activity activity = null;
+ private cgSettings settings = null;
+ private cgBase base = null;
+ private cgWarning warning = null;
+ private PowerManager pm = null;
+ private cgGeo geo = null;
+ private cgDirection dir = null;
+ private cgUpdateLoc geoUpdate = new update();
+ private cgUpdateDir dirUpdate = new updateDir();
+ private Double dstLatitude = null;
+ private Double dstLongitude = null;
+ private Double cacheHeading = new Double(0);
+ private Double northHeading = new Double(0);
+ private String title = null;
+ private String name = null;
+ private TextView navType = null;
+ private TextView navAccuracy = null;
+ private TextView navSatellites = null;
+ private TextView navLocation = null;
+ private TextView distanceView = null;
+ private TextView headingView = null;
+ private cgCompass compassView = null;
+ private updaterThread updater = null;
+ private Handler updaterHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (compassView != null) {
+ compassView.updateNorth(northHeading, cacheHeading);
+ }
+ } catch (Exception e) {
+ Log.e(cgSettings.tag, "cgeonavigate.updaterHandler: " + e.toString());
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // class init
+ activity = this;
+ res = this.getResources();
+ app = (cgeoapplication) this.getApplication();
+ settings = new cgSettings(this, getSharedPreferences(cgSettings.preferences, 0));
+ base = new cgBase(app, settings, getSharedPreferences(cgSettings.preferences, 0));
+ warning = new cgWarning(this);
+
+ // set layout
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ if (settings.skin == 1) {
+ setTheme(R.style.light);
+ } else {
+ setTheme(R.style.dark);
+ }
+ setContentView(R.layout.navigate);
+ base.setTitle(activity, res.getString(R.string.compass_title));
+
+ // google analytics
+ base.sendAnal(activity, "/navigate");
+
+ // sensor & geolocation manager
+ if (geo == null) {
+ geo = app.startGeo(activity, geoUpdate, base, settings, warning, 0, 0);
+ }
+ if (settings.useCompass == 1 && dir == null) {
+ dir = app.startDir(activity, dirUpdate, warning);
+ }
+
+ // get parameters
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ title = extras.getString("geocode");
+ name = extras.getString("name");
+ dstLatitude = extras.getDouble("latitude");
+ dstLongitude = extras.getDouble("longitude");
+
+ if (name != null && name.length() > 0) {
+ if (title != null && title.length() > 0) {
+ title = title + ": " + name;
+ } else {
+ title = name;
+ }
+ }
+ } else {
+ Intent pointIntent = new Intent(activity, cgeopoint.class);
+ activity.startActivity(pointIntent);
+
+ finish();
+ return;
+ }
+
+ if (title != null && title.length() > 0) {
+ app.setAction(title);
+ } else if (name != null && name.length() > 0) {
+ app.setAction(name);
+ }
+
+ // set header
+ setTitle();
+ setDestCoords();
+
+ // get textviews once
+ compassView = (cgCompass) findViewById(R.id.rose);
+
+ // start updater thread
+ updater = new updaterThread(updaterHandler);
+ updater.start();
+
+ if (geo != null) {
+ geoUpdate.updateLoc(geo);
+ }
+ if (dir != null) {
+ dirUpdate.updateDir(dir);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ settings.load();
+
+ if (title != null && title.length() > 0) {
+ app.setAction(title);
+ } else if (name != null && name.length() > 0) {
+ app.setAction(name);
+ }
+
+ // sensor & geolocation manager
+ if (geo == null) {
+ geo = app.startGeo(activity, geoUpdate, base, settings, warning, 0, 0);
+ }
+ if (settings.useCompass == 1 && dir == null) {
+ dir = app.startDir(activity, dirUpdate, warning);
+ }
+
+ // keep backlight on
+ if (pm == null) {
+ pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ }
+
+ // updater thread
+ if (updater == null) {
+ updater = new updaterThread(updaterHandler);
+ updater.start();
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (geo != null) {
+ geo = app.removeGeo();
+ }
+ if (dir != null) {
+ dir = app.removeDir();
+ }
+
+ super.onStop();
+ }
+
+ @Override
+ public void onPause() {
+ if (geo != null) {
+ geo = app.removeGeo();
+ }
+ if (dir != null) {
+ dir = app.removeDir();
+ }
+
+ super.onPause();
+ }
+
+ @Override
+ public void onDestroy() {
+ if (geo != null) {
+ geo = app.removeGeo();
+ }
+ if (dir != null) {
+ dir = app.removeDir();
+ }
+
+ compassView.destroyDrawingCache();
+ compassView = null;
+
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (settings.useCompass == 1) {
+ menu.add(0, 1, 0, res.getString(R.string.use_gps)).setIcon(android.R.drawable.ic_menu_compass);
+ } else {
+ menu.add(0, 1, 0, res.getString(R.string.use_compass)).setIcon(android.R.drawable.ic_menu_compass);
+ }
+ menu.add(0, 0, 0, res.getString(R.string.caches_on_map)).setIcon(android.R.drawable.ic_menu_mapmode);
+ menu.add(0, 2, 0, res.getString(R.string.destination_set)).setIcon(android.R.drawable.ic_menu_edit);
+ if (coordinates != null && coordinates.size() > 1) {
+ SubMenu subMenu = menu.addSubMenu(0, 3, 0, res.getString(R.string.destination_select)).setIcon(android.R.drawable.ic_menu_myplaces);
+
+ int cnt = 4;
+ for (cgCoord coordinate : coordinates) {
+ subMenu.add(0, cnt, 0, coordinate.name + " (" + coordinate.type + ")");
+ cnt++;
+ }
+
+ return true;
+ } else {
+ menu.add(0, 3, 0, res.getString(R.string.destination_select)).setIcon(android.R.drawable.ic_menu_myplaces).setEnabled(false);
+
+ return true;
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+
+ MenuItem item;
+ item = menu.findItem(1);
+ if (settings.useCompass == 1) {
+ item.setTitle(res.getString(R.string.use_gps));
+ } else {
+ item.setTitle(res.getString(R.string.use_compass));
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+
+ if (id == 0) {
+ Intent mapIntent = new Intent(activity, settings.getMapFactory().getMapClass());
+ mapIntent.putExtra("detail", false);
+ mapIntent.putExtra("latitude", dstLatitude);
+ mapIntent.putExtra("longitude", dstLongitude);
+
+ activity.startActivity(mapIntent);
+ } else if (id == 1) {
+ if (settings.useCompass == 1) {
+ settings.useCompass = 0;
+
+ if (dir != null) {
+ dir = app.removeDir();
+ }
+
+ SharedPreferences.Editor prefsEdit = getSharedPreferences(cgSettings.preferences, 0).edit();
+ prefsEdit.putInt("usecompass", settings.useCompass);
+ prefsEdit.commit();
+ } else {
+ settings.useCompass = 1;
+
+ if (dir == null) {
+ dir = app.startDir(activity, dirUpdate, warning);
+ }
+
+ SharedPreferences.Editor prefsEdit = getSharedPreferences(cgSettings.preferences, 0).edit();
+ prefsEdit.putInt("usecompass", settings.useCompass);
+ prefsEdit.commit();
+ }
+ } else if (id == 2) {
+ Intent pointIntent = new Intent(activity, cgeopoint.class);
+ activity.startActivity(pointIntent);
+
+ finish();
+ return true;
+ } else if (id > 3 && coordinates != null && coordinates.get(id - 4) != null) {
+ cgCoord coordinate = coordinates.get(id - 4);
+
+ title = coordinate.name;
+ dstLatitude = coordinate.latitude;
+ dstLongitude = coordinate.longitude;
+ setTitle();
+ setDestCoords();
+ updateDistanceInfo();
+
+ Log.d(cgSettings.tag, "destination set: " + title + " (" + String.format(Locale.getDefault(), "%.8f", dstLatitude) + " | " + String.format(Locale.getDefault(), "%.8f", dstLatitude) + ")");
+ return true;
+ }
+
+ return false;
+ }
+
+ private void setTitle() {
+ if (title != null && title.length() > 0) {
+ base.setTitle(activity, title);
+ } else {
+ base.setTitle(activity, res.getString(R.string.navigation));
+ }
+ }
+
+ private void setDestCoords() {
+ if (dstLatitude == null || dstLatitude == null) {
+ return;
+ }
+
+ ((TextView) findViewById(R.id.destination)).setText(base.formatCoordinate(dstLatitude, "lat", true) + " | " + base.formatCoordinate(dstLongitude, "lon", true));
+ }
+
+ public void setDest(Double lat, Double lon) {
+ if (lat == null || lon == null) {
+ return;
+ }
+
+ title = "some place";
+ setTitle();
+ setDestCoords();
+
+ dstLatitude = lat;
+ dstLongitude = lon;
+ updateDistanceInfo();
+ }
+
+ public HashMap<String, Double> getCoordinatesNow() {
+ HashMap<String, Double> coordsNow = new HashMap<String, Double>();
+ if (geo != null) {
+ coordsNow.put("latitude", geo.latitudeNow);
+ coordsNow.put("longitude", geo.longitudeNow);
+ }
+ return coordsNow;
+ }
+
+ private void updateDistanceInfo() {
+ if (geo == null || geo.latitudeNow == null || geo.longitudeNow == null || dstLatitude == null || dstLongitude == null) {
+ return;
+ }
+
+ if (distanceView == null) {
+ distanceView = (TextView) findViewById(R.id.distance);
+ }
+ if (headingView == null) {
+ headingView = (TextView) findViewById(R.id.heading);
+ }
+
+ cacheHeading = cgBase.getHeading(geo.latitudeNow, geo.longitudeNow, dstLatitude, dstLongitude);
+ distanceView.setText(base.getHumanDistance(cgBase.getDistance(geo.latitudeNow, geo.longitudeNow, dstLatitude, dstLongitude)));
+ headingView.setText(String.format(Locale.getDefault(), "%.0f", cacheHeading) + "°");
+ }
+
+ private class update extends cgUpdateLoc {
+
+ @Override
+ public void updateLoc(cgGeo geo) {
+ if (geo == null) {
+ return;
+ }
+
+ try {
+ if (navType == null || navLocation == null || navAccuracy == null) {
+ navType = (TextView) findViewById(R.id.nav_type);
+ navAccuracy = (TextView) findViewById(R.id.nav_accuracy);
+ navSatellites = (TextView) findViewById(R.id.nav_satellites);
+ navLocation = (TextView) findViewById(R.id.nav_location);
+ }
+
+ if (geo.latitudeNow != null && geo.longitudeNow != null) {
+ String satellites = null;
+ if (geo.satellitesVisible != null && geo.satellitesFixed != null && geo.satellitesFixed > 0) {
+ satellites = res.getString(R.string.loc_sat) + ": " + geo.satellitesFixed + "/" + geo.satellitesVisible;
+ } else if (geo.satellitesVisible != null) {
+ satellites = res.getString(R.string.loc_sat) + ": 0/" + geo.satellitesVisible;
+ } else {
+ satellites = "";
+ }
+ navSatellites.setText(satellites);
+
+ if (geo.gps == -1) {
+ navType.setText(res.getString(R.string.loc_last));
+ } else if (geo.gps == 0) {
+ navType.setText(res.getString(R.string.loc_net));
+ } else {
+ navType.setText(res.getString(R.string.loc_gps));
+ }
+
+ if (geo.accuracyNow != null) {
+ if (settings.units == cgSettings.unitsImperial) {
+ navAccuracy.setText("±" + String.format(Locale.getDefault(), "%.0f", (geo.accuracyNow * 3.2808399)) + " ft");
+ } else {
+ navAccuracy.setText("±" + String.format(Locale.getDefault(), "%.0f", geo.accuracyNow) + " m");
+ }
+ } else {
+ navAccuracy.setText(null);
+ }
+
+ if (geo.altitudeNow != null) {
+ String humanAlt;
+ if (settings.units == cgSettings.unitsImperial) {
+ humanAlt = String.format("%.0f", (geo.altitudeNow * 3.2808399)) + " ft";
+ } else {
+ humanAlt = String.format("%.0f", geo.altitudeNow) + " m";
+ }
+ navLocation.setText(base.formatCoordinate(geo.latitudeNow, "lat", true) + " | " + base.formatCoordinate(geo.longitudeNow, "lon", true) + " | " + humanAlt);
+ } else {
+ navLocation.setText(base.formatCoordinate(geo.latitudeNow, "lat", true) + " | " + base.formatCoordinate(geo.longitudeNow, "lon", true));
+ }
+
+ updateDistanceInfo();
+ } else {
+ navType.setText(null);
+ navAccuracy.setText(null);
+ navLocation.setText(res.getString(R.string.loc_trying));
+ }
+
+ if (settings.useCompass == 0 || (geo.speedNow != null && geo.speedNow > 5)) { // use GPS when speed is higher than 18 km/h
+ if (geo != null && geo.bearingNow != null) {
+ northHeading = geo.bearingNow;
+ } else {
+ northHeading = new Double(0);
+ }
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to update location.");
+ }
+ }
+ }
+
+ private class updateDir extends cgUpdateDir {
+
+ @Override
+ public void updateDir(cgDirection dir) {
+ if (dir == null || dir.directionNow == null) {
+ return;
+ }
+
+ if (geo == null || geo.speedNow == null || geo.speedNow <= 5) { // use compass when speed is lower than 18 km/h
+ northHeading = dir.directionNow;
+ }
+ }
+ }
+
+ private class updaterThread extends Thread {
+
+ private Handler handler = null;
+
+ public updaterThread(Handler handlerIn) {
+ handler = handlerIn;
+ }
+
+ @Override
+ public void run() {
+ while (!Thread.currentThread().isInterrupted()) {
+ if (handler != null) {
+ handler.sendMessage(new Message());
+ }
+
+ try {
+ Thread.sleep(20);
+ } catch (Exception e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+
+ public void goHome(View view) {
+ base.goHome(activity);
+ }
+
+ public void goManual(View view) {
+ try {
+ AppManualReaderClient.openManual(
+ "c-geo",
+ "c:geo-compass",
+ activity,
+ "http://cgeo.carnero.cc/manual/");
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+} \ No newline at end of file