it.trilogis.android.fao.WorldWindActivity.java Source code

Java tutorial

Introduction

Here is the source code for it.trilogis.android.fao.WorldWindActivity.java

Source

/*
 * Copyright (C) 2014 Trilogis S.r.l.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package it.trilogis.android.fao;

import gov.nasa.worldwind.BasicFactory;
import gov.nasa.worldwind.BasicView;
import gov.nasa.worldwind.Model;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WorldWindowGLSurfaceView;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.layers.Layer;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.GPSMarker;
import gov.nasa.worldwind.render.ShapeAttributes;
import gov.nasa.worldwind.terrain.ElevationModel;
import gov.nasa.worldwind.terrain.ZeroElevationModel;
import it.trilogis.android.fao.constants.Constants;
import it.trilogis.android.fao.unzip.ClearCacheTask;
import it.trilogis.android.fao.unzip.UnzipTask;
import it.trilogis.android.fao.utils.FileUtils;
import it.trilogis.android.fao.utils.WorldWindUtils;
import it.trilogis.android.ww.dialogs.GpsSettingsDialog;
import it.trilogis.android.ww.dialogs.SettingsDialogFragment;
import it.trilogis.android.ww.dialogs.TrilogisAboutDialogFragment;
import it.trilogis.android.ww.dialogs.SettingsDialogFragment.OnSettingsChangedListener;

import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

/**
 * @author Nicola Dorigatti, Nicola Meneghini
 */
public class WorldWindActivity extends FragmentActivity
        implements UnzipTask.Callbacks, ClearCacheTask.Callbacks, GpsStatus.Listener {

    private LocationManager lm = null;

    private RenderableLayer markerLayer;
    private boolean firstLoc = true;

    // Setup the config file at runtime
    static {
        System.setProperty("gov.nasa.worldwind.app.config.document", "config/wwandroidfao.xml");
    }

    public static final String TAG = "FAOWWApplication";

    private boolean fileEx = false;
    private boolean fileFound = false;
    private File mFile = null;

    // WW items
    protected WorldWindowGLSurfaceView wwd;

    private boolean[] layersExist = new boolean[] { false, false, false, false, false };

    private boolean[] layersEnabled = new boolean[] { true, true, true, true, true };

    private int exaggeration;
    private int gpsMeters;
    private int gpsSeconds;
    private boolean gpsUpdate;
    private boolean gpsIsOn;
    Timer timerGPS;
    SettingsDialogFragment settings = null;
    GpsSettingsDialog gpsSettings = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        checkExistinglayers();

        SharedPreferences prefs = getPreferences(MODE_PRIVATE);

        for (int i = 0; i < Constants.layers.length; i++) {
            layersEnabled[i] = prefs.getBoolean(Constants.layers[i], layersExist[i]);
            if (layersEnabled[i] && !layersExist[i]) {
                layersEnabled[i] = false;
            }
        }

        if (layersEnabled[0] && layersEnabled[1]) {
            layersEnabled[1] = false;
        }
        exaggeration = prefs.getInt(Constants.PROP_EXAGGERATION, Constants.DEFAULT_EXAGGERATION);
        gpsUpdate = prefs.getBoolean(Constants.PROP_GPS_UPDATE, Constants.DEFAULT_GPS_UPDATE);
        gpsSeconds = prefs.getInt(Constants.PROP_GPS_SECONDS, Constants.DEFAULT_GPS_SECONDS);
        gpsMeters = prefs.getInt(Constants.PROP_GPS_METERS, Constants.DEFAULT_GPS_METERS);

        //control if it's possible save cache files
        File fileDir = getExternalCacheDir();
        if (null == fileDir) {
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.setMessage(R.string.alert_message_nocache);
            alert.setCancelable(false);
            alert.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            });
            alert.show();
        }
        if (null != fileDir && fileDir.exists() && fileDir.canWrite()) {
            // create .nomedia file, so pictures will not be visible in the gallery (otherwise, it's really awful to see all of the tiles as images!)
            File output = new File(fileDir, ".nomedia");
            if (output.exists()) {
                Log.d(TAG, "No need to create .nomedia file, it's already there! : " + output.getAbsolutePath());
            } else {
                // lets create the file
                boolean fileCreated = false;
                try {
                    fileCreated = output.createNewFile();
                } catch (IOException e) {
                    Log.e(TAG, "IOException while creating .nomedia: " + e.getMessage());
                }
                if (!fileCreated) {
                    Log.e(TAG, ".nomedia file not created!");
                } else {
                    Log.d(TAG, ".nomedia file created!");
                }
            }
            //find and unpack zip
            findFileZip();
        }

        // Setup system property for the file store
        System.setProperty("gov.nasa.worldwind.platform.user.store", fileDir.getAbsolutePath());
        Log.w(TAG, "Directory is: " + fileDir.getAbsolutePath());
        // set the contentview
        this.setContentView(R.layout.activity_world_wind);
        //can start using context and views

        //location initialize
        lm = (LocationManager) this.getSystemService(LOCATION_SERVICE);
        lm.addGpsStatusListener(this);

        // And initialize the WorldWindow Model and View
        this.wwd = (WorldWindowGLSurfaceView) this.findViewById(R.id.wwd);
        this.wwd.setModel((Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME));
        Bundle extras = getIntent().getExtras();
        if (extras == null) {
            this.setupView();
        } else {
            //if is call by another app
            this.setupCustomView(extras);
        }
        this.setupTextViews();
    }

    @Override
    protected void onPause() {
        super.onPause();

        // Pause the OpenGL ES rendering thread.
        this.wwd.onPause();

        // Pause GPS search and timer
        if (null != timerGPS)
            timerGPS.cancel();
        if (null != lm)
            lm.removeUpdates(locationListener);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Resume the OpenGL ES rendering thread.
        this.wwd.onResume();

        // Set view at last GPS position and search position
        if (gpsUpdate) {
            setLookAtLastLocation();
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsSeconds * 1000, gpsMeters, locationListener);
            startGPSTimer();
        }

        // Add enable layers
        addElevationLayer();
        addLayers();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.options, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_trilogis:
            // Trilogis about
            TrilogisAboutDialogFragment aboutDialog = new TrilogisAboutDialogFragment();
            aboutDialog.show(getSupportFragmentManager(), "TrilogisAboutDialog");
            break;
        case R.id.settings:
            // Settings
            settings = new SettingsDialogFragment(layersExist, layersEnabled, exaggeration, gpsSeconds, gpsMeters,
                    gpsUpdate);
            settings.setOnSettingChangeListener(settingsListener);
            settings.setCancelable(false);
            settings.show(getFragmentManager(), "Settings");
            break;
        default:
            return super.onOptionsItemSelected(item);
        }
        return true;
    }

    // Set the view with default parameters.
    protected void setupView() {
        BasicView view = (BasicView) this.wwd.getView();
        Globe globe = this.wwd.getModel().getGlobe();

        // Set the initial position to "Africa"
        view.setLookAtPosition(Position.fromDegrees(Constants.DEFAULT_LATITUDE, Constants.DEFAULT_LONGITUDE,
                globe.getElevation(Angle.fromDegrees(Constants.DEFAULT_LATITUDE),
                        Angle.fromDegrees(Constants.DEFAULT_LONGITUDE))));
        view.setHeading(Angle.fromDegrees(Constants.DEFAULT_VIEW_HEADING));
        view.setTilt(Angle.fromDegrees(Constants.DEFAULT_VIEW_TILT));
        view.setRange(Constants.DEFAULT_VIEW_DISTANCE_KM);
    }

    // Set the view with custom parameters passed with bundle.
    protected void setupCustomView(Bundle bundle) {
        try {

            // Get parameters
            double lat = bundle.getDouble("latitude", Constants.DEFAULT_LATITUDE);
            double lon = bundle.getDouble("longitude", Constants.DEFAULT_LONGITUDE);
            double range = bundle.getDouble("range", Constants.DEFAULT_VIEW_DISTANCE_KM);
            double heading = bundle.getDouble("heading", Constants.DEFAULT_VIEW_HEADING);
            double tilt = bundle.getDouble("tilt", Constants.DEFAULT_VIEW_TILT);

            BasicView view = (BasicView) this.wwd.getView();
            Globe globe = this.wwd.getModel().getGlobe();

            // Set the initial position to lat and long passed, where you can see the WMS Layers
            if (lat > 0 && lon > 0) {
                view.setLookAtPosition(Position.fromDegrees(lat, lon,
                        globe.getElevation(Angle.fromDegrees(lat), Angle.fromDegrees(lon))));
            } else {
                view.setLookAtPosition(Position.fromDegrees(Constants.DEFAULT_LATITUDE, Constants.DEFAULT_LONGITUDE,
                        globe.getElevation(Angle.fromDegrees(Constants.DEFAULT_LATITUDE),
                                Angle.fromDegrees(Constants.DEFAULT_LONGITUDE))));
            }

            // Set range
            if (range > 0) {
                view.setRange(range);
            } else {
                view.setRange(Constants.DEFAULT_VIEW_DISTANCE_KM);
            }

            // Set the direction of view
            if (heading >= 0 && heading <= 360) {
                view.setHeading(Angle.fromDegrees(heading));
            } else {
                view.setHeading(Angle.fromDegrees(Constants.DEFAULT_VIEW_HEADING));
            }

            // Set angle of view
            if (tilt >= 0 && tilt <= 90) {
                view.setTilt(Angle.fromDegrees(tilt));
            } else {
                view.setTilt(Angle.fromDegrees(Constants.DEFAULT_VIEW_TILT));
            }

        } catch (Exception e) {
            setupView();
        }
    }

    protected void setupTextViews() {
        // Set textviews where wwd print latitude and longitude of the point clicked 
        TextView latTextView = (TextView) findViewById(R.id.latvalue);
        this.wwd.setLatitudeText(latTextView);
        TextView lonTextView = (TextView) findViewById(R.id.lonvalue);
        this.wwd.setLongitudeText(lonTextView);
        this.wwd.setCoordinateInDegrees(true);
    }

    private void findFileZip() {

        try {
            mFile = new File(Constants.EXTERNAL_PATH + "/", Constants.FILE_NAME);
            if (mFile.exists()) {
                fileEx = true;
                fileFound = true;
            } else {
                fileEx = false;
                fileFound = false;
            }
        } catch (Exception e) {
            fileEx = false;
            fileFound = false;
        }
        if (!fileEx) {
            mFile = new File(Environment.getExternalStorageDirectory() + "/", Constants.FILE_NAME);
            if (mFile.exists()) {
                fileFound = true;
            }
        }

        if (fileFound) {
            File dir = new File(getExternalCacheDir() + "/" + Constants.URLWORLD);
            long size = FileUtils.folderSize(dir);
            if (size > 1048576) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(WorldWindActivity.this);

                alertDialog.setCancelable(false);
                alertDialog.setTitle(R.string.unzip_dialog_title);
                alertDialog.setMessage(R.string.unzip_dialog_text);

                alertDialog.setPositiveButton(R.string.replace, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        // Clear cache and start unzip when it finish
                        ClearCacheTask c = new ClearCacheTask(true, WorldWindActivity.this, WorldWindActivity.this);
                        c.execute();
                    }
                });

                alertDialog.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        // Do nothing
                    }
                });

                alertDialog.setNeutralButton(R.string.append, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int id) {
                        unzipFile();
                    }
                });
                alertDialog.show();
            } else {
                unzipFile();
            }

        } else {
            // Control if there are tiles cached
            File dir = new File(getExternalCacheDir() + "/" + Constants.URLWORLD);
            long size = FileUtils.folderSize(dir);
            if (size < 1048576) {
                AlertDialog.Builder alert = new AlertDialog.Builder(this);
                alert.setMessage(R.string.alert_message_nolayers);
                alert.setCancelable(false);
                alert.setNegativeButton(android.R.string.ok, null);
                alert.show();
            }

        }
    }

    public void redrawWorld() {
        wwd.redraw();
    }

    // Define a listener that responds to location updates
    LocationListener locationListener = new LocationListener() {
        public void onLocationChanged(Location location) {
            if (null != wwd) {

                BasicView view = (BasicView) wwd.getView();
                Globe globe = wwd.getModel().getGlobe();
                Position pos = Position.fromDegrees(location.getLatitude(), location.getLongitude(),
                        globe.getElevation(Angle.fromDegrees(location.getLatitude()),
                                Angle.fromDegrees(location.getLongitude())));

                if (firstLoc) {
                    firstLoc = false;
                    view.animateTo(pos, Constants.DEFAULT_GPS_DISTANCE_KM, view.getHeading(), view.getTilt(), wwd);
                }
                addMarker(pos);

                double lat = location.getLatitude();
                int deglat = (int) lat;
                if (lat < 0) {
                    lat = (lat - deglat) * (-60);
                } else {
                    lat = (lat - deglat) * 60;
                }
                int minlat = (int) lat;
                lat = (lat - minlat) * 60;
                int seclat = (int) lat;

                double lon = location.getLongitude();
                int deglon = (int) lon;
                if (lon < 0) {
                    lon = (lon - deglon) * (-60);
                } else {
                    lon = (lon - deglon) * 60;
                }
                int minlon = (int) lon;
                lon = (lon - minlon) * 60;
                int seclon = (int) lon;

                TextView latTextView = (TextView) findViewById(R.id.poslatvalue);
                latTextView.setText("" + deglat + " " + minlat + "\' " + seclat + "\"");
                TextView lonTextView = (TextView) findViewById(R.id.poslonvalue);
                lonTextView.setText("" + deglon + " " + minlon + "\' " + seclon + "\"");

                if (null != gpsSettings && gpsSettings.isAdded()) {
                    gpsSettings.dismiss();
                }
                resetGPSTimer();
            }

        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
            // do nothing
        }

        public void onProviderEnabled(String provider) {
            //Search the position if button it was clicked
            gpsIsOn = true;
            if (null != gpsSettings && gpsSettings.isAdded()) {
                gpsSettings.dismiss();
            }
        }

        public void onProviderDisabled(String provider) {
            gpsIsOn = false;
            if (null != gpsSettings && gpsSettings.isAdded()) {
                gpsSettings.dismiss();
            }
            gpsSettings = new GpsSettingsDialog(getString(R.string.turn_on_gps), gpsListener, false);
            gpsSettings.show(getSupportFragmentManager(), "GPS settings");

        }
    };

    // Set View at last know location
    protected void setLookAtLastLocation() {
        Location lastLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (null != lastLocation) {

            BasicView view = (BasicView) wwd.getView();
            Globe globe = wwd.getModel().getGlobe();
            Position pos = new Position(Angle.fromDegrees(lastLocation.getLatitude()),
                    Angle.fromDegrees(lastLocation.getLongitude()),
                    globe.getElevation(Angle.fromDegrees(lastLocation.getLatitude()),
                            Angle.fromDegrees(lastLocation.getLongitude())));
            view.setLookAtPosition(pos);
            addMarker(pos);
            view.setRange(Constants.LAST_LOCATION_VIEW_DISTANCE_KM);
        }
    }

    // Move view at last know location
    protected void moveAtLastLocation() {
        Location lastLocation = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (null != lastLocation) {

            addMarker(Position.fromDegrees(lastLocation.getLatitude(), lastLocation.getLongitude()));

            BasicView view = (BasicView) wwd.getView();
            view.animateTo(Position.fromDegrees(lastLocation.getLatitude(), lastLocation.getLongitude()),
                    Constants.DEFAULT_GPS_DISTANCE_KM, view.getHeading(), view.getTilt(), wwd);
        }
    }

    public void unzipFile() {
        final UnzipTask unzipTask = new UnzipTask(mFile, WorldWindActivity.this, WorldWindActivity.this);
        unzipTask.execute();
    }

    // ---------------- CLEAR CACHE TASK CALLBACKS -------------------------

    @Override
    public void unzipTileFile() {
        unzipFile();
    }

    // ---------------------------------------------------------------------

    // ---------------- UNZIP TASK CALLBACKS -------------------------------

    @Override
    public void finishActivity() {
        WorldWindActivity.this.finish();
    }

    @Override
    public void finishUnzip() {

        removeLayers();

        checkExistinglayers();

        for (int i = 0; i < Constants.layers.length; i++) {
            layersEnabled[i] = layersExist[i];
        }

        if (layersEnabled[0] && layersEnabled[1]) {
            layersEnabled[1] = false;
        }

        // Restore preferences
        SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
        for (int i = 0; i < Constants.layers.length; i++) {
            if (layersExist[i]) {
                editor.putBoolean(Constants.layers[i], layersEnabled[i]);
            }
        }
        editor.commit();

        // Add Layers
        addElevationLayer();
        addLayers();

        wwd.redraw();
    }

    // ---------------------------------------------------------------------

    protected void setEnableLayer(String layerName, boolean enable) {
        for (Layer lyr : wwd.getModel().getLayers()) {
            if (null != lyr) {
                if (lyr.getName().equals(layerName)) {
                    lyr.setEnabled(enable);
                }
            }
        }
    }

    protected void removeLayer(String layerName) {
        for (Layer lyr : wwd.getModel().getLayers()) {
            if (null != lyr) {
                if (lyr.getName().equals(layerName)) {
                    wwd.getModel().getLayers().remove(lyr);
                }
            }
        }
    }

    protected void removeLayers() {
        for (Layer lyr : wwd.getModel().getLayers()) {
            if (null != lyr) {
                for (int i = 0; i < Constants.layers.length; i++) {
                    if (lyr.getName().equals(Constants.layers[i])) {
                        wwd.getModel().getLayers().remove(lyr);
                    }
                }
            }
        }
    }

    private Layer createLayer(String path) {
        File xml = new File(path);
        if (xml.exists()) {
            Object o = BasicFactory.create(AVKey.LAYER_FACTORY, xml);
            return (Layer) o;
        }
        return null;
    }

    // Add Elevation layer from file xml in cache folder
    private void addElevationLayer() {
        if (exaggeration == 0) {
            wwd.getModel().getGlobe().setElevationModel(new ZeroElevationModel());
        } else {
            File xml = new File(getExternalCacheDir() + "/" + Constants.URLWORLD + Constants.ELEVATION_NAME + "/",
                    Constants.ELEVATION_NAME + ".xml");
            if (xml.exists()) {
                ElevationModel em = WorldWindUtils.getElevationModel(xml);
                em.setNetworkRetrievalEnabled(false);
                wwd.getModel().getGlobe().setElevationModel(em);
                wwd.getSceneController().setVerticalExaggeration(this.exaggeration);
            } else {
                wwd.getModel().getGlobe().setElevationModel(new ZeroElevationModel());
            }
        }
    }

    // Set vertical exaggeration and elevation layer if need
    private void setVerticalExaggeration(int exaggeration) {
        this.exaggeration = exaggeration;
        if (this.exaggeration == 0) {
            wwd.getModel().getGlobe().setElevationModel(new ZeroElevationModel());
        } else {
            File xml = new File(getExternalCacheDir() + "/" + Constants.URLWORLD + Constants.ELEVATION_NAME + "/",
                    Constants.ELEVATION_NAME + ".xml");
            if (xml.exists()) {
                if (wwd.getModel().getGlobe().getElevationModel() instanceof ZeroElevationModel) {
                    ElevationModel em = WorldWindUtils.getElevationModel(xml);
                    em.setNetworkRetrievalEnabled(false);
                    wwd.getModel().getGlobe().setElevationModel(em);
                } else {
                    wwd.getSceneController().setVerticalExaggeration(this.exaggeration);
                }

            } else {
                wwd.getModel().getGlobe().setElevationModel(new ZeroElevationModel());
            }
        }
    }

    // Add all layers except elevation from files xml in cache folder
    private void addLayers() {

        for (int i = 0; i < Constants.layers.length; i++) {
            File xml = new File(getExternalCacheDir() + "/" + Constants.URLWORLD + Constants.layers[i] + "/",
                    Constants.layers[i] + ".xml");
            if (xml.exists()) {
                Layer lyr = createLayer(xml.getAbsolutePath());
                if (null != lyr) {
                    lyr.setName(Constants.layers[i]);
                    lyr.setNetworkRetrievalEnabled(false);
                    if (!layersEnabled[i]) {
                        lyr.setEnabled(false);
                    }
                    wwd.getModel().getLayers().addIfAbsent(lyr);
                }
            } else {
                removeLayer(Constants.layers[i]);
            }
        }

    }

    // Check if files xml to define layers are present or not.
    private void checkExistinglayers() {

        for (int i = 0; i < Constants.layers.length; i++) {
            File xml = new File(getExternalCacheDir() + "/" + Constants.URLWORLD + Constants.layers[i] + "/",
                    Constants.layers[i] + ".xml");
            if (xml.exists()) {
                layersExist[i] = true;
            } else {
                layersExist[i] = false;
                layersEnabled[i] = false;
            }
        }

    }

    // Add marker in view at position
    private void addMarker(Position pos) {

        GPSMarker c = new GPSMarker(Position.fromDegrees(pos.latitude.degrees, pos.longitude.degrees, 0),
                Constants.MARKER_SIDE, Constants.MARKER_HEIGHT);
        c.setAltitudeMode(AVKey.RELATIVE_TO_GROUND);
        //c.setGPSMarkerType(AVKey.LINEAR);
        ShapeAttributes attrs = new BasicShapeAttributes();
        attrs.setOutlineColor(Constants.MARKER_COLOR);
        c.setAttributes(attrs);

        if (null != markerLayer) {
            this.wwd.getModel().getLayers().remove(markerLayer);
            markerLayer.clearList();
            markerLayer = null;
        }

        markerLayer = new RenderableLayer();
        markerLayer.addRenderable(c);

        this.wwd.getModel().getLayers().add(markerLayer);
    }

    //Callbacks from settings dialog
    SettingsDialogFragment.OnSettingsChangedListener settingsListener = new OnSettingsChangedListener() {

        @Override
        public void onSettingChange() {
            // Change preferences
            SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();

            for (int i = 0; i < Constants.layers.length; i++) {
                if (layersExist[i]) {
                    editor.putBoolean(Constants.layers[i], layersEnabled[i]);
                }
            }
            editor.putInt(Constants.PROP_EXAGGERATION, exaggeration);
            editor.putBoolean(Constants.PROP_GPS_UPDATE, gpsUpdate);
            editor.putInt(Constants.PROP_GPS_SECONDS, gpsSeconds);
            editor.putInt(Constants.PROP_GPS_METERS, gpsMeters);

            editor.commit();
        }

        @Override
        public void onLayerChange(int index, boolean checked) {
            setEnableLayer(Constants.layers[index], checked);
            layersEnabled[index] = checked;
        }

        @Override
        public void onExaggerationChange(int exaggeration) {
            setVerticalExaggeration(exaggeration);
        }

        @Override
        public void onGpsChange(int gpsS, int gpsM) {
            gpsMeters = gpsM;
            gpsSeconds = gpsS;
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsSeconds * 1000, gpsMeters, locationListener);
        }

        @Override
        public void onGpsEnableChange(boolean enable) {
            gpsUpdate = enable;
            if (gpsUpdate) {
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsSeconds * 1000, gpsMeters,
                        locationListener);
                startGPSTimer();
            } else {
                lm.removeUpdates(locationListener);
                timerGPS.cancel();
            }
        }
    };

    GpsSettingsDialog.OnGpsCloseListener gpsListener = new GpsSettingsDialog.OnGpsCloseListener() {

        @Override
        public void onCloseGpsSettings(boolean reset) {
            //no gpsUpdate
            if (!reset) {
                if (!gpsIsOn) {
                    gpsUpdate = false;
                    lm.removeUpdates(locationListener);
                    if (null != timerGPS) {
                        timerGPS.cancel();
                    }
                    if (null != settings && settings.isAdded()) {
                        settings.setGpsUpdate(gpsUpdate);
                    }
                }
            } else {
                startGPSTimer();
            }
        }

        @Override
        public void onNoGpsUpdate() {
            gpsUpdate = false;
            lm.removeUpdates(locationListener);
            if (null != timerGPS) {
                timerGPS.cancel();
            }
        }
    };

    @Override
    public void onGpsStatusChanged(int event) {
        if (event == GpsStatus.GPS_EVENT_STARTED) {
            gpsIsOn = true;
            gpsUpdate = true;
            startGPSTimer();
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsSeconds * 1000, gpsMeters, locationListener);
            if (null != gpsSettings && gpsSettings.isAdded()) {
                gpsSettings.dismiss();
            }
        }
    }

    public void startGPSTimer() {
        TimerTask taskGPS = new TimerTask() {

            @Override
            public void run() {
                if (null != gpsSettings && gpsSettings.isAdded()) {
                    gpsSettings.dismiss();
                }
                gpsSettings = new GpsSettingsDialog(getString(R.string.reset_gps), gpsListener, true);
                gpsSettings.show(getSupportFragmentManager(), "GPS settings");
            }
        };
        if (null != timerGPS) {
            timerGPS.cancel();
        }
        timerGPS = new Timer();
        timerGPS.scheduleAtFixedRate(taskGPS, Constants.GPS_RESET, Long.MAX_VALUE);
    }

    public void resetGPSTimer() {
        if (null != timerGPS) {
            timerGPS.cancel();
        }
        startGPSTimer();
    }

}