it.geosolutions.geocollect.android.map.GeoCollectMapActivity.java Source code

Java tutorial

Introduction

Here is the source code for it.geosolutions.geocollect.android.map.GeoCollectMapActivity.java

Source

/*******************************************************************************
 * Copyright 2014-2015 GeoSolutions
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *******************************************************************************/
package it.geosolutions.geocollect.android.map;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mapsforge.android.maps.BackgroundSourceType;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.mapgenerator.MapRenderer;
import org.mapsforge.android.maps.mapgenerator.TileCache;
import org.mapsforge.android.maps.mapgenerator.databaserenderer.DatabaseRenderer;
import org.mapsforge.android.maps.mapgenerator.mbtiles.MbTilesDatabaseRenderer;
import org.mapsforge.core.model.GeoPoint;
import org.mapsforge.core.model.MapPosition;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;
import it.geosolutions.android.map.MapsActivity;
import it.geosolutions.android.map.MapsActivity.PARAMETERS;
import it.geosolutions.android.map.activities.GetFeatureInfoLayerListActivity;
import it.geosolutions.android.map.activities.MBTilesLayerOpacitySettingActivity;
import it.geosolutions.android.map.activities.MapActivityBase;
import it.geosolutions.android.map.activities.about.InfoView;
import it.geosolutions.android.map.control.CoordinateControl;
import it.geosolutions.android.map.control.LocationControl;
import it.geosolutions.android.map.control.MapControl;
import it.geosolutions.android.map.control.MapInfoControl;
import it.geosolutions.android.map.control.MarkerControl;
import it.geosolutions.android.map.database.SpatialDataSourceManager;
import it.geosolutions.android.map.dto.MarkerDTO;
import it.geosolutions.android.map.fragment.sources.SourcesFragment;
import it.geosolutions.android.map.geostore.activities.GeoStoreResourceDetailActivity;
import it.geosolutions.android.map.geostore.activities.GeoStoreResourcesActivity;
import it.geosolutions.android.map.geostore.model.Resource;
import it.geosolutions.android.map.mapstore.model.MapStoreConfiguration;
import it.geosolutions.android.map.mbtiles.MbTilesLayer;
import it.geosolutions.android.map.model.Attribute;
import it.geosolutions.android.map.model.Feature;
import it.geosolutions.android.map.model.Layer;
import it.geosolutions.android.map.model.MSMMap;
import it.geosolutions.android.map.overlay.MarkerOverlay;
import it.geosolutions.android.map.overlay.items.DescribedMarker;
import it.geosolutions.android.map.overlay.managers.MultiSourceOverlayManager;
import it.geosolutions.android.map.overlay.managers.OverlayManager;
import it.geosolutions.android.map.overlay.switcher.LayerSwitcherFragment;
import it.geosolutions.android.map.preferences.EditPreferences;
import it.geosolutions.android.map.style.StyleManager;
import it.geosolutions.android.map.utils.MapFilesProvider;
import it.geosolutions.android.map.utils.MarkerUtils;
import it.geosolutions.android.map.utils.SpatialDbUtils;
import it.geosolutions.android.map.utils.StorageUtils;
import it.geosolutions.android.map.view.AdvancedMapView;
import it.geosolutions.geocollect.android.app.CreditsActivity;
import it.geosolutions.geocollect.android.app.R;
import it.geosolutions.geocollect.android.core.login.LoginActivity;
import it.geosolutions.geocollect.android.core.login.LogoutActivity;
import it.geosolutions.geocollect.android.core.mission.PendingMissionListActivity;
import it.geosolutions.geocollect.android.core.mission.utils.NavUtils;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerActivityConfiguration;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerAdapter;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerItem;

/**
 * Custom Map to use with GeoCollect application
 * This version adds a button to zoom to the initial BBOX
 * There are also a custom layout on the
 * resources layout-land/activity_map.xml
 * to place the button bar on the bottom, as in the other maps
 * 
 * @author Lorenzo Pini (lorenzo.pini@geo-solutions.it)
 */
public class GeoCollectMapActivity extends MapActivityBase {

    private static String TAG = GeoCollectMapActivity.class.getName();

    // default path for files
    private static final File MAP_DIR = MapFilesProvider.getBaseDirectoryFile();
    private static final File MAP_FILE = MapFilesProvider.getBackgroundMapFile();

    // ------------------------------------------------------
    // SAVE INSTANCE STATE BUNDLE PARAMETERS
    // ------------------------------------------------------
    private boolean dbLoaded;

    // ------------------------------------------------------
    // PUBLIC VARIABLES
    // ------------------------------------------------------
    public AdvancedMapView mapView;

    public OverlayManager overlayManager;

    // ------------------------------------------------------
    // CONSTANTS
    // ------------------------------------------------------

    /** FEATURE_DEFAULT_ID */
    private static final String FEATURE_DEFAULT_ID = "OGC_FID";

    /** DB_LOADED_FLAG */
    private static final String DB_LOADED_FLAG = "dbLoaded";

    private static final String FEATUREIDFIELD_FLAG = "fidField";

    /** Chosen featureID field */
    private String featureIdField;

    /** CANCONFRIM_FLAG */
    private static final String CANCONFRIM_FLAG = "canConfirm_flag";

    private static boolean canConfirm;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    /**
     * LAYOUT PARAMETERS
     */
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    private View mLayerMenu;

    private MultiSourceOverlayManager layerManager;

    protected MapInfoControl mic;

    protected NavDrawerActivityConfiguration navConf;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inf = getSupportMenuInflater();
        inf.inflate(R.menu.simple_map_menu, (Menu) menu);

        return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        MenuInflater inf = getSupportMenuInflater();
        inf.inflate(R.menu.simple_map_menu, (Menu) menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        // center on the marker, preferably the updated
        if (item.getItemId() == R.id.center) {
            centerMapFile();
        } else
        // Activate the filter control
        if (item.getItemId() == R.id.filter) {
            if (mic != null && mic.getActivationListener() != null) {
                mic.getActivationListener().onClick(item.getActionView());
            }
        } else
        // Drawer part
        if (item.getItemId() == android.R.id.home) {

            if (mDrawerList != null && mDrawerLayout.isDrawerOpen(mDrawerList)) {
                mDrawerLayout.closeDrawer(mDrawerList);
            } else {
                if (mDrawerList != null) {
                    mDrawerLayout.openDrawer(mDrawerList);
                }
                if (mLayerMenu != null) {
                    mDrawerLayout.closeDrawer(mLayerMenu);
                }
            }
            // layer menu part
        } else if (item.getItemId() == R.id.layer_menu_action) {
            if (mLayerMenu != null && mDrawerLayout.isDrawerOpen(mLayerMenu)) {
                mDrawerLayout.closeDrawer(mLayerMenu);
            } else {
                if (mLayerMenu != null) {
                    mDrawerLayout.openDrawer(mLayerMenu);
                }
                if (mDrawerList != null) {
                    mDrawerLayout.closeDrawer(mDrawerList);
                }
            }
        } else if (item.getItemId() == R.id.settings) {
            Intent pref = new Intent(this, EditPreferences.class);
            startActivity(pref);
        } else if (item.getItemId() == R.id.infoview) {
            Intent info = new Intent(this, InfoView.class);
            startActivity(info);
        } else if (item.getItemId() == R.id.exitview) {
            confirmExit();
        }
        return super.onOptionsItemSelected(item);

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // setup loading
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setSupportProgressBarIndeterminateVisibility(false);
        super.onCreate(savedInstanceState);

        //
        // LAYOUT INITIALIZATION
        //
        setContentView(R.layout.geocollect_main);

        //
        // MAP INITIALIZATION
        //
        // create overlay manager
        boolean mapLoaded = initMap(savedInstanceState);
        layerManager = new MultiSourceOverlayManager(mapView);
        overlayManager = layerManager;
        // setup slide menu(es)
        //setupDrawerLayout();
        dbLoaded = initDb();
        // if something went wrong during db and map initialization,
        // we should stop
        if (!mapLoaded && !dbLoaded) {
            Toast.makeText(this, "DB not loaded", Toast.LENGTH_LONG).show();
        }

        // SETUP MAP

        if (savedInstanceState != null) {
            layerManager.restoreInstanceState(savedInstanceState);
        } else {
            layerManager.defaultInit();

            if (getIntent() != null && getIntent().getExtras() != null
                    && getIntent().getExtras().containsKey(MapsActivity.MSM_MAP)) {

                layerManager.loadMap((MSMMap) getIntent().getExtras().getSerializable(MapsActivity.MSM_MAP));

            } else {
                boolean dontLoadMBTileLayer = MapFilesProvider
                        .getBackgroundSourceType() == BackgroundSourceType.MBTILES ? true : false;
                MSMMap map = SpatialDbUtils.mapFromDb(dontLoadMBTileLayer);
                StorageUtils.setupSources(this);
                //This adds layers also if its called loadMap but it will not order layers
                //layerManager.loadMap(map);
                //so use this instead
                addLayersOrdered(map.layers);
            }

        }

        //
        // LEFT MENU INITIALIZATION
        //
        navConf = getNavDrawerConfiguration();

        mTitle = mDrawerTitle = getTitle();

        mDrawerLayout = (DrawerLayout) findViewById(navConf.getDrawerLayoutId());
        mDrawerList = (ListView) findViewById(navConf.getLeftDrawerId());
        mDrawerList.setAdapter(navConf.getBaseAdapter());
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer,
                navConf.getDrawerOpenDesc(), navConf.getDrawerCloseDesc()) {
            public void onDrawerClosed(View view) {
                getSupportActionBar().setTitle(mTitle);
                supportInvalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                getSupportActionBar().setTitle(mDrawerTitle);
                supportInvalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // CONTEXT MENU
        this.registerForContextMenu(mapView);
        mapView.getMapScaleBar().setShowMapScaleBar(true);

        overlayManager.setMarkerOverlay(new MarkerOverlay());
        createMarkers(savedInstanceState);

        String action = getIntent().getAction();
        if (Intent.ACTION_VIEW.equals(action)) {
            // prevent editing
            canConfirm = false;
        } else {
            // Default edit
            canConfirm = true;
            this.addConfirmButton();
        }
        addControls(savedInstanceState);

        centerMapFile();
        loadFromBundle();

        mic = new ReturningMapInfoControl();
        mic.activity = this;
        mic.mapView = mapView;

        // if the mapView had some controls, get the group of them
        // this check is needed until the map library will have named groups
        List<MapControl> mcList = mapView.getControls();
        if (mcList != null && !mcList.isEmpty()) {
            MapControl mc;
            boolean found = false;
            for (int i = 0; i < mcList.size() && !found; i++) {
                mc = mcList.get(i);
                if (mc.getGroup() != null) {
                    mic.setGroup(mc.getGroup());
                    mic.getGroup().add(mic);
                    found = true;
                }
            }

        }

        mapView.addControl(mic);
        mic.instantiateListener();

        // Enable Home button on ActionBar
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

    }

    /**
     * 
     * @return
     */
    protected NavDrawerActivityConfiguration getNavDrawerConfiguration() {

        NavDrawerItem[] menu = NavUtils.getNavMenu(this);
        // setup navigation configuration options
        NavDrawerActivityConfiguration navDrawerActivityConfiguration = new NavDrawerActivityConfiguration();
        navDrawerActivityConfiguration.setMainLayout(R.layout.geocollect_main);
        navDrawerActivityConfiguration.setDrawerLayoutId(R.id.drawer_layout);
        navDrawerActivityConfiguration.setLeftDrawerId(R.id.left_drawer);
        navDrawerActivityConfiguration.setNavItems(menu);
        navDrawerActivityConfiguration.setBaseAdapter(new NavDrawerAdapter(this, R.layout.navdrawer_item, menu));
        return navDrawerActivityConfiguration;
    }

    /**
     * load a map from bundle
     */
    private void loadFromBundle() {
        Bundle data = getIntent().getExtras();
        if (data == null)
            return;
        Resource resource = (Resource) data.getSerializable(PARAMETERS.RESOURCE);
        if (resource != null) {
            String geoStoreUrl = data.getString(PARAMETERS.GEOSTORE_URL);
            loadGeoStoreResource(resource, geoStoreUrl);
        }

    }

    /**
     * Resume the state of:
     * 
     * * tile cache * Controls
     */
    @Override
    protected void onResume() {
        super.onResume();
        loadPersistencePreferences();
        checkIfMapViewNeedsBackgroundUpdate();
        // Refresh control beacuse any changes can be changed
        for (MapControl mic : mapView.getControls()) {
            mic.refreshControl(GetFeatureInfoLayerListActivity.BBOX_REQUEST,
                    GetFeatureInfoLayerListActivity.BBOX_REQUEST, null);
        }

        // Some debug
        Intent i = getIntent();
        if (i != null) {
            String a = i.getAction();
            Log.v(TAG, "onResume() Action:" + a);
        }
    }

    /**
     * add the confirm button to the control bar
     */
    private void addConfirmButton() {
        Log.v(TAG, "adding confirm button");
        ImageButton b = (ImageButton) findViewById(R.id.button_confirm_marker_position);
        b.setVisibility(View.VISIBLE);
        final MapActivityBase activity = this;
        b.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (!canConfirm) {
                    Toast.makeText(activity, R.string.error_unable_getfeature_db, Toast.LENGTH_LONG).show();
                    return;
                }

                new AlertDialog.Builder(activity).setTitle(R.string.button_confirm_marker_position_title)
                        .setMessage(R.string.button_confirm_marker_position)
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                Intent returnIntent = new Intent();
                                // get current markers
                                ArrayList<DescribedMarker> markers = overlayManager.getMarkerOverlay().getMarkers();
                                // serialize markers in the response
                                returnIntent.putParcelableArrayListExtra(MapsActivity.PARAMETERS.MARKERS,
                                        MarkerUtils.getMarkersDTO(markers));
                                setResult(RESULT_OK, returnIntent);
                                finish();
                                return;
                                // if you don't want to return data:
                                // setResult(RESULT_CANCELED, returnIntent);
                                // finish();
                                // activity.finish();
                            }

                        }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                // do nothing
                            }
                        }).show();

            }
        });
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);

        savedInstanceState.putBoolean(DB_LOADED_FLAG, dbLoaded);

        savedInstanceState.putString(FEATUREIDFIELD_FLAG, featureIdField);

        savedInstanceState.putBoolean(CANCONFRIM_FLAG, canConfirm);
        // MARKERS
        // get current markers
        overlayManager.saveInstanceState(savedInstanceState);
        for (MapControl mc : mapView.getControls()) {
            mc.saveState(savedInstanceState);
        }
    }

    /**
     * Save the layer state
     */
    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "onPause saving layers");
    }

    /**
     * Force a double tap to close the app
     * 
     * @Override public void onBackPressed() {
     * 
     *           //You may also add condition if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) // in case of
     *           Fragment-based add if (mRecentlyBackPressed) { mExitHandler.removeCallbacks(mExitRunnable); mExitHandler = null;
     *           super.onBackPressed(); } else { mRecentlyBackPressed = true; Toast.makeText(this, "press again to exit", Toast.LENGTH_SHORT).show();
     *           mExitHandler.postDelayed(mExitRunnable, delay); } }
     */

    /**
     * Ask to confirm when exit
     */
    @Override
    public void onBackPressed() {

        confirmExit();

    }

    /**
     * Show a confirm message to exit
     */
    public void confirmExit() {
        boolean confirmOnExit = getIntent().getExtras().getBoolean(MapsActivity.PARAMETERS.CONFIRM_ON_EXIT, true);
        if (confirmOnExit) {
            new AlertDialog.Builder(this).setTitle(R.string.button_confirm_exit_title)
                    .setMessage(R.string.button_confirm_exit)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                            return;
                        }
                    }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // do nothing
                        }
                    }).show();
        } else {
            finish();
        }
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // Restore UI state from the savedInstanceState.
        // This bundle has also been passed to onCreate.
        dbLoaded = savedInstanceState.getBoolean(DB_LOADED_FLAG);

        featureIdField = savedInstanceState.getString(FEATUREIDFIELD_FLAG);
        canConfirm = savedInstanceState.getBoolean(CANCONFRIM_FLAG);

        // Restore state of the controls?

    }

    /**
     * Create the markers and add them to the MarkerOverlay Gets it from the Intent or from the savedInstanceState Assign them the proper <GeoPoint>
     * if missing
     * 
     * @param savedInstanceState
     */
    private void createMarkers(Bundle savedInstanceState) {
        List<MarkerDTO> markerDTOs = null;
        // add the OverlayItem to the ArrayItemizedOverlay
        ArrayList<DescribedMarker> markers = null;
        if (savedInstanceState != null) {
            markerDTOs = savedInstanceState.getParcelableArrayList(MapsActivity.PARAMETERS.MARKERS);
            markers = MarkerUtils.markerDTO2DescribedMarkers(this, markerDTOs);
        } else {
            markerDTOs = getIntent().getParcelableArrayListExtra(MapsActivity.PARAMETERS.MARKERS);
            markers = MarkerUtils.markerDTO2DescribedMarkers(this, markerDTOs);
            // retrieve geopoint if missing
            if (getIntent().getExtras() == null) {
                return;
            }
            featureIdField = getIntent().getExtras().getString(PARAMETERS.FEATURE_ID_FIELD);
            if (featureIdField == null) {
                featureIdField = FEATURE_DEFAULT_ID;
            }
            if (!MarkerUtils.assignFeaturesFromDb(markers, featureIdField)) {
                Toast.makeText(this, R.string.error_unable_getfeature_db, Toast.LENGTH_LONG).show();
                canConfirm = false;
                // TODO dialog : download features for this area?
            }
        }
        // create an ItemizedOverlay with the default marker
        overlayManager.getMarkerOverlay().getOverlayItems().addAll(markers);
    }

    /**
     * Initializes the database
     * 
     * @return true if the initialization was successful
     */
    private boolean initDb() {
        // init styleManager
        StyleManager.getInstance().init(this, MAP_DIR);
        // init Db
        SpatialDataSourceManager dbManager = SpatialDataSourceManager.getInstance();

        try {
            // Only if not already loaded some tables
            if (dbManager.getSpatialVectorTables(false).size() <= 0) {
                dbManager.init(MAP_DIR);
            }
        } catch (Exception e) {

            return false;
        }
        return true;
    }

    /**
     * Initialize the map with Controls and background
     * 
     * @param savedInstanceState
     * 
     * @return
     */
    private boolean initMap(Bundle savedInstanceState) {
        // setContentView(R.layout.activity_map);
        Log.v(TAG, "Map Activated");
        LayoutInflater inflater = LayoutInflater.from(GeoCollectMapActivity.this);
        inflater.inflate(R.layout.activity_map, (FrameLayout) findViewById(R.id.content_frame));

        this.mapView = (AdvancedMapView) findViewById(R.id.advancedMapView);

        mapView.setClickable(true);
        mapView.setBuiltInZoomControls(true);

        // mapView.setDebugSettings(new DebugSettings(true, true, false));

        mapView.getMapZoomControls().setZoomLevelMax((byte) 24);
        mapView.getMapZoomControls().setZoomLevelMin((byte) 1);

        final String filePath = PreferenceManager.getDefaultSharedPreferences(this)
                .getString(MapView.MAPSFORGE_BACKGROUND_FILEPATH, null);
        final int type = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(this)
                .getString(MapView.MAPSFORGE_BACKGROUND_RENDERER_TYPE, "0"));
        File mapfile = null;

        // if the map file was edited in the preferences
        if (filePath != null && type == 0) {
            mapfile = new File(filePath);
        }

        if (mapfile != null && mapfile.exists()) {
            // use it
            mapView.setMapFile(new File(filePath));

        } else if (MAP_FILE != null) {

            Log.i(TAG, "setting background file");
            mapView.setMapFile(MAP_FILE);
            loadPersistencePreferences();

        } else {
            Log.i(TAG, "unable to set background file");
            // return false;
        }

        return true;
    }

    /**
     * Add controls to the mapView and to the Buttons
     * 
     * @param savedInstanceState
     */
    private void addControls(Bundle savedInstanceState) {
        String action = getIntent().getAction();
        Log.v(TAG, "action: " + action);

        // Coordinate Control
        mapView.addControl(new CoordinateControl(mapView, true));
        List<MapControl> group = new ArrayList<MapControl>();

        // Info Control
        MapInfoControl ic;
        if (getIntent().hasExtra(MapsActivity.PARAMETERS.CUSTOM_MAPINFO_CONTROL)) {
            ic = (MapInfoControl) getIntent().getParcelableExtra(MapsActivity.PARAMETERS.CUSTOM_MAPINFO_CONTROL);
            ic.activity = this;
            ic.mapView = mapView;
            ic.instantiateListener();
        } else {
            ic = new MapInfoControl(mapView, this);
        }
        ic.setActivationButton((ImageButton) findViewById(R.id.ButtonInfo));

        mapView.addControl(ic);

        if (!Intent.ACTION_VIEW.equals(action)) {
            Log.v(TAG, "Adding MarkerControl");

            // Marker Control
            MarkerControl mc = new MarkerControl(mapView);
            // activation button
            ImageButton mcbmb = (ImageButton) findViewById(R.id.ButtonMarker);
            mcbmb.setVisibility(View.VISIBLE);
            mc.setActivationButton(mcbmb);
            // info button
            ImageButton mcib = (ImageButton) findViewById(R.id.marker_info_button);
            mcib.setVisibility(View.VISIBLE);
            mc.setInfoButton(mcib);

            mapView.addControl(mc);
            group.add(mc);
            mc.setGroup(group);
            mc.setMode(MarkerControl.MODE_EDIT);
        }

        // My location Control
        LocationControl lc = new LocationControl(mapView);
        lc.setActivationButton((ImageButton) findViewById(R.id.ButtonLocation));
        mapView.addControl(lc);

        // create and add group
        group.add(ic);

        ic.setGroup(group);

        // Set modes for controls
        if (Intent.ACTION_VIEW.equals(action)) {
            ic.setMode(MapInfoControl.MODE_VIEW);
        } else if (Intent.ACTION_EDIT.equals(action)) {
            ic.setMode(MapInfoControl.MODE_EDIT);
            // Default edit mode
        } else {
            ic.setMode(MapInfoControl.MODE_EDIT);
        }
        if (savedInstanceState != null) {
            for (MapControl c : mapView.getControls()) {
                c.restoreState(savedInstanceState);
            }
        }

    }

    /**
     * center the map on the markers
     */
    public void centerMapFile() {
        MarkerOverlay mo = mapView.getMarkerOverlay();
        MapPosition mp = mapView.getMapViewPosition().getMapPosition();

        Intent intent = getIntent();
        if (intent.hasExtra(PARAMETERS.LAT) && intent.hasExtra(PARAMETERS.LON)
                && intent.hasExtra(PARAMETERS.ZOOM_LEVEL)) {
            double lat = intent.getDoubleExtra(PARAMETERS.LAT, 43.68411);
            double lon = intent.getDoubleExtra(PARAMETERS.LON, 10.84899);
            byte zoom_level = intent.getByteExtra(PARAMETERS.ZOOM_LEVEL, (byte) 13);
            byte zoom_level_min = intent.getByteExtra(PARAMETERS.ZOOM_LEVEL_MIN, (byte) 0);
            byte zoom_level_max = intent.getByteExtra(PARAMETERS.ZOOM_LEVEL_MAX, (byte) 30);
            /*
             * ArrayList<MarkerDTO> list_marker = intent.getParcelableArrayListExtra(PARAMETERS.MARKERS); MarkerDTO mark = list_marker.get(0);
             */
            mp = new MapPosition(new GeoPoint(lat, lon), zoom_level);
            mapView.getMapViewPosition().setMapPosition(mp);
            mapView.getMapZoomControls().setZoomLevelMin(zoom_level_min);
            mapView.getMapZoomControls().setZoomLevelMax(zoom_level_max);
        } else {
            if (mo != null) {
                // support only one marker
                MapPosition newMp = MarkerUtils.getMarkerCenterZoom(mo.getMarkers(), mp);
                if (newMp != null) {
                    mapView.getMapViewPosition().setMapPosition(newMp);
                }
            }
        }
    }

    /**
     * Center the map to a point and zoomLevel
     * 
     * @param pp
     * @param zoomlevel
     */
    public void setPosition(GeoPoint pp, byte zoomlevel) {

        mapView.getMapViewPosition().setMapPosition(new MapPosition(pp, zoomlevel));
    }

    /**
     * Opena the Data List activity
     * 
     * @param item
     * @return
     */

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent incomingIntent) {
        super.onActivityResult(requestCode, resultCode, incomingIntent);
        Log.d(TAG, "onActivityResult");

        if (requestCode == LoginActivity.REQUEST_LOGIN) {

            if (resultCode == RESULT_CANCELED) {
                // user cancelled to enter credentials
                Toast.makeText(getBaseContext(), getString(R.string.login_canceled), Toast.LENGTH_LONG).show();
                finish();
                return;
            }
        }
        if (requestCode == LogoutActivity.REQUEST_LOGOUT) {
            if (resultCode == LogoutActivity.LOGGED_OUT) {
                // there is a notification in LogoutActivity already
                startActivityForResult(new Intent(this, LoginActivity.class), LoginActivity.REQUEST_LOGIN);
                return;
            }
        }

        if (requestCode == LayerSwitcherFragment.OPACITY_SETTIN_REQUEST_ID) {

            final int newValue = PreferenceManager.getDefaultSharedPreferences(getBaseContext())
                    .getInt(MBTilesLayerOpacitySettingActivity.MBTILES_OPACITY_ID, 192);

            ArrayList<Layer> layers = layerManager.getLayers();

            for (Layer l : layers) {
                if (l instanceof MbTilesLayer) {
                    l.setOpacity(newValue);
                    layerManager.redrawLayer(l);

                }
            }

            // its not necessary to handle the other stuff
            return;
        }

        if (requestCode == GetFeatureInfoLayerListActivity.BBOX_REQUEST && resultCode == RESULT_OK) {
            // the response can contain a feature to use to replace the current marker
            // on the map
            manageMarkerSubstitutionAction(incomingIntent);
        }

        // controls can be refreshed getting the result of an intent, in this case
        // each control knows which intent he sent with their requestCode/resultCode
        for (MapControl control : mapView.getControls()) {
            control.refreshControl(requestCode, resultCode, incomingIntent);
        }
        // reload stores in the panel (we do it everyTime, maybe there is a better way
        SourcesFragment sf = (SourcesFragment) getSupportFragmentManager().findFragmentById(R.id.right_drawer);
        if (sf != null) {
            sf.reloadStores();
        }
        // manager mapstore configuration load
        if (incomingIntent == null) {
            return;
        }
        Bundle b = incomingIntent.getExtras();
        if (requestCode == MapsActivity.DATAPROPERTIES_REQUEST_CODE) {
            mapView.getOverlayController().redrawOverlays();
            // close right drawer
            if (mLayerMenu != null) {
                if (mDrawerLayout.isDrawerOpen(mLayerMenu)) {
                    mDrawerLayout.closeDrawer(mLayerMenu);
                }
            }
        }
        Resource resource = (Resource) incomingIntent
                .getSerializableExtra(GeoStoreResourceDetailActivity.PARAMS.RESOURCE);
        if (resource != null) {
            String geoStoreUrl = incomingIntent.getStringExtra(GeoStoreResourcesActivity.PARAMS.GEOSTORE_URL);
            loadGeoStoreResource(resource, geoStoreUrl);
        }
        if (b.containsKey(MapsActivity.MAPSTORE_CONFIG)) {
            overlayManager
                    .loadMapStoreConfig((MapStoreConfiguration) b.getSerializable(MapsActivity.MAPSTORE_CONFIG));
        }
        if (b.containsKey(MapsActivity.MSM_MAP)) {
            layerManager.loadMap((MSMMap) b.getSerializable(MapsActivity.MSM_MAP));

        }
        ArrayList<Layer> layersToAdd = (ArrayList<Layer>) b.getSerializable(MapsActivity.LAYERS_TO_ADD);
        if (layersToAdd != null) {
            addLayers(layersToAdd);
        }

    }

    /**
     * Add layers to the map
     * 
     * @param layersToAdd
     */
    private void addLayers(ArrayList<Layer> layersToAdd) {
        ArrayList<Layer> layers = new ArrayList<Layer>(layerManager.getLayers());
        layers.addAll(layersToAdd);
        layerManager.setLayers(layers);
        // close right drawer
        if (mLayerMenu != null) {
            if (mDrawerLayout.isDrawerOpen(mLayerMenu)) {
                mDrawerLayout.closeDrawer(mLayerMenu);
            }
        }
    }

    /**
     * Load a geostore resource on the map
     * 
     * @param resource the resource id
     * @param geoStoreUrl
     */
    private void loadGeoStoreResource(Resource resource, String geoStoreUrl) {
        MapUtils.loadMapStoreConfig(geoStoreUrl, resource, overlayManager, mapView);
        // close right drawer
        if (mLayerMenu != null) {
            if (mDrawerLayout.isDrawerOpen(mLayerMenu)) {
                mDrawerLayout.closeDrawer(mLayerMenu);
            }
        }
    }

    /**
     * Manages the marker substitution
     */
    private void manageMarkerSubstitutionAction(Intent data) {

        @SuppressWarnings("unchecked")
        ArrayList<Attribute> arrayList = (ArrayList<Attribute>) data.getExtras()
                .getSerializable(GetFeatureInfoLayerListActivity.RESULT_FEATURE_EXTRA);
        Feature f = new Feature(arrayList);
        String layer = data.getExtras().getString(GetFeatureInfoLayerListActivity.LAYER_FEATURE_EXTRA);

        Attribute a = f.getAttribute(featureIdField);

        String attributeValue = null;
        if (a != null) {
            attributeValue = a.getValue();
        }
        replaceMarker(layer, featureIdField, attributeValue, f);

    }

    /**
     * Replace the default marker with position and properties from the arguments
     * 
     * @param layer
     * @param attributeName
     * @param attributeValue
     * @param f
     */
    private void replaceMarker(String layer, String attributeName, String attributeValue, Feature f) {
        DescribedMarker marker = getDefaultMarker();

        if (marker != null) {
            setMarkerProperties(layer, attributeName, attributeValue, attributeValue, marker, f);
        }
    }

    /**
     * @param layer
     * @param attributeName
     * @param a
     * @param attributeValue
     * @param marker
     * @param f
     */
    private void setMarkerProperties(String layer, String attributeName, String id, String attributeValue,
            DescribedMarker marker, Feature f) {
        GeoPoint p = SpatialDbUtils.getGeopointFromLayer(layer, attributeName, attributeValue);
        // get Only the first
        if (p != null) {
            // TODO ask if you want to change
            // if yes move and center map
            marker.setGeoPoint(p);
            marker.setFeatureId(id);
            marker.setFeature(f);
            mapView.redraw();
            canConfirm = true;
        } else {
            Toast.makeText(this, R.string.error_getting_data_from_database, Toast.LENGTH_LONG).show();
        }
    }

    /**
     * get a marker from markerOverlay. The one highlighted or the first one
     * 
     * @return
     */
    private DescribedMarker getDefaultMarker() {
        MarkerOverlay m = mapView.getMarkerOverlay();
        // add the marker overlay if not present
        if (m == null) {
            overlayManager.toggleOverlayVisibility(R.id.markers, true);
            m = mapView.getMarkerOverlay();
        }

        DescribedMarker marker = m.getHighlighted();
        if (marker == null) {
            List<DescribedMarker> markers = m.getMarkers();
            if (markers.size() > 0) {
                marker = markers.get(0);
            } else {
                // TODO add a new marker
            }
        }
        return marker;
    }

    @Override
    public void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        TileCache fileSystemTileCache = this.mapView.getFileSystemTileCache();

        Log.v(TAG, "Capacity: " + fileSystemTileCache.getCapacity() + ", Persistence: "
                + fileSystemTileCache.isPersistent());
        if (mDrawerToggle != null) {
            mDrawerToggle.syncState();
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mDrawerToggle != null) {
            mDrawerToggle.onConfigurationChanged(newConfig);
        }
        // Checks the orientation of the screen for landscape and portrait and set portrait mode always
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        }
    }

    /**
     * Load tile caching preferences used sharedPreferences : * TileCachePersistence * TileCacheSize
     */
    public void loadPersistencePreferences() {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        boolean persistent = sharedPreferences.getBoolean("TileCachePersistence", true);
        Log.v(TAG,
                "Cache Size: "
                        + sharedPreferences.getInt("TileCacheSize", MapsActivity.FILE_SYSTEM_CACHE_SIZE_DEFAULT)
                        + ", Persistent: " + persistent);
        int capacity = Math.min(
                sharedPreferences.getInt("TileCacheSize", MapsActivity.FILE_SYSTEM_CACHE_SIZE_DEFAULT),
                MapsActivity.FILE_SYSTEM_CACHE_SIZE_MAX);
        TileCache fileSystemTileCache = this.mapView.getFileSystemTileCache();

        fileSystemTileCache.setPersistent(persistent);
        fileSystemTileCache.setCapacity(capacity);
        // text size
        String textScaleDefault = getString(R.string.preferences_text_scale_default);
        this.mapView.setTextScale(Float.parseFloat(sharedPreferences.getString("mapTextScale", textScaleDefault)));
    }

    /**
     * checks if the preferences of the background renderer changed if so, the mapview is informed and is cleared and redrawed
     */
    public void checkIfMapViewNeedsBackgroundUpdate() {
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        final boolean thingsChanged = prefs.getBoolean(MapView.MAPSFORGE_BACKGROUND_FILEPATH_CHANGED, false);
        if (!thingsChanged)
            return;

        final BackgroundSourceType currentMapRendererType = this.mapView.getMapRendererType();

        String filePath = prefs.getString(MapView.MAPSFORGE_BACKGROUND_FILEPATH, null);
        final String defaultType = getApplicationContext().getPackageName()
                .equals("it.geosolutions.geocollect.android.app") ? "1" : "0";
        BackgroundSourceType type = BackgroundSourceType.values()[Integer
                .parseInt(prefs.getString(MapView.MAPSFORGE_BACKGROUND_RENDERER_TYPE, defaultType))];

        final Editor ed = prefs.edit();
        ed.putBoolean(MapView.MAPSFORGE_BACKGROUND_FILEPATH_CHANGED, false);
        ed.commit();

        File mapFile = new File(filePath);
        if (mapFile == null || !mapFile.exists()) {
            mapFile = MapFilesProvider.getBackgroundMapFile();
            filePath = mapFile.getPath();
            type = BackgroundSourceType.MAPSFORGE;
        }

        // 1. renderer changed
        if (type != currentMapRendererType) {

            MapRenderer mapRenderer = null;
            switch (type) {
            case MAPSFORGE:
                if (filePath == null) {
                    throw new IllegalArgumentException("no filepath selected to change to mapsforge renderer");
                }
                mapView.setMapFile(new File(filePath));
                mapRenderer = new DatabaseRenderer(mapView.getMapDatabase());
                // TODO it was MBTILES with no or dimmed mbtiles layer, add MBTiles layer ?

                MSMMap map = SpatialDbUtils.mapFromDb(false);
                Log.d(TAG, "Mapsforge maps includes " + map.layers.size() + " layers");

                addLayersOrdered(map.layers);

                break;
            case MBTILES:
                mapRenderer = new MbTilesDatabaseRenderer(getBaseContext(), filePath);

                MSMMap map2 = SpatialDbUtils.mapFromDb(true);

                layerManager.setLayers(map2.layers);

                break;
            default:
                break;
            }
            if (mDrawerToggle != null) {
                mDrawerToggle.syncState();
            }
            mapView.setRenderer(mapRenderer, true);
            mapView.clearAndRedrawMapView();
            MapFilesProvider.setBackgroundSourceType(type);

        } else if (filePath != null && !filePath.equals(mapView.getMapRenderer().getFileName())) {

            // 2.renderer is the same but file changed
            switch (type) {
            case MAPSFORGE:
                mapView.setMapFile(new File(filePath));
                break;
            case MBTILES:
                mapView.setRenderer(new MbTilesDatabaseRenderer(getBaseContext(), filePath), true);
                break;
            default:
                break;
            }
            mapView.clearAndRedrawMapView();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            // mDrawerLayout.openDrawer(mDrawerList);
            // return true;

        }
        return super.onKeyUp(keyCode, event);
    }

    public void addLayersOrdered(final ArrayList<Layer> layers) {

        ArrayList<Layer> originalLayers = layers;
        ArrayList<Layer> orderedLayers = new ArrayList<Layer>();

        // check if there is a MBTiles layer which needs to be ordered
        boolean layersContainMBTilesLayer = false;
        for (Layer l : originalLayers) {
            if (l instanceof MbTilesLayer) {
                layersContainMBTilesLayer = true;
                break;
            }
        }
        // if there is, add this flag to wait until it has been added
        boolean mbTilesAdded = !layersContainMBTilesLayer;

        while (!originalLayers.isEmpty()) {

            final Layer layer = originalLayers.get(originalLayers.size() - 1); // get last

            if (layer instanceof MbTilesLayer) {

                final int currentValue = PreferenceManager.getDefaultSharedPreferences(getBaseContext())
                        .getInt(MBTilesLayerOpacitySettingActivity.MBTILES_OPACITY_ID, 192);
                layer.setOpacity(currentValue);
                orderedLayers.add(layer);
                mbTilesAdded = true;
                originalLayers.remove(layer);
                Log.d(TAG, "mbtiles layer added , size " + orderedLayers.size());
            } else if (mbTilesAdded == true) {
                orderedLayers.add(layer);
                originalLayers.remove(layer);
                Log.d(TAG, "other added , size " + orderedLayers.size());
            }

        }

        layerManager.setLayers(orderedLayers);
    }

    public View getLayerMenu() {
        return mLayerMenu;
    }

    public View getDrawerList() {
        return mDrawerList;
    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    public void selectItem(int position) {
        NavDrawerItem selectedItem = navConf.getNavItems()[position];

        this.onNavItemSelected(selectedItem.getId());
        mDrawerList.setItemChecked(position, true);

        if (selectedItem.updateActionBarTitle()) {
            setTitle(selectedItem.getLabel());
        }

        if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
            mDrawerLayout.closeDrawer(mDrawerList);
        }
    }

    protected void onNavItemSelected(int id) {
        if (id != 900) {
            Intent intent = new Intent();
            intent.putExtra(PendingMissionListActivity.KEY_MAP_RESULT, id);
            setResult(RESULT_OK, intent);
            finish();
        } else {
            startActivity(new Intent(this, CreditsActivity.class));
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
                this.mDrawerLayout.closeDrawer(this.mDrawerList);
            } else {
                this.mDrawerLayout.openDrawer(this.mDrawerList);
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * Display a confirm prompt before logging out the user
     */
    public static void confirmLogout(final Activity act) {
        final Context ctx = act.getBaseContext();
        new AlertDialog.Builder(act).setTitle(R.string.action_logout).setMessage(R.string.button_confirm_logout)
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {

                        //clear user data
                        final Editor ed = PreferenceManager.getDefaultSharedPreferences(ctx).edit();

                        ed.putString(LoginActivity.PREFS_USER_EMAIL, null);
                        ed.putString(LoginActivity.PREFS_USER_FORENAME, null);
                        ed.putString(LoginActivity.PREFS_USER_SURNAME, null);
                        ed.putString(LoginActivity.PREFS_PASSWORD, null);
                        ed.putString(LoginActivity.PREFS_AUTH_KEY, null);
                        ed.putString(LoginActivity.PREFS_USER_ENTE, null);

                        ed.commit();

                        Toast.makeText(ctx, ctx.getString(R.string.logout_logged_out), Toast.LENGTH_LONG).show();

                        if (act != null) {
                            act.startActivityForResult(new Intent(ctx, LoginActivity.class),
                                    LoginActivity.REQUEST_LOGIN);
                        }

                    }
                }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        // do nothing
                    }
                }).show();
    }

}