/*******************************************************************************
* 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();
}
}