/*******************************************************************************
* 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.core.mission;
import it.geosolutions.android.map.MapsActivity;
import it.geosolutions.android.map.MapsActivity.DrawerMode;
import it.geosolutions.android.map.model.Layer;
import it.geosolutions.android.map.model.MSMMap;
import it.geosolutions.android.map.utils.SpatialDbUtils;
import it.geosolutions.android.map.view.MapViewManager;
import it.geosolutions.geocollect.android.app.BuildConfig;
import it.geosolutions.geocollect.android.app.CreditsActivity;
import it.geosolutions.geocollect.android.core.GeoCollectApplication;
import it.geosolutions.geocollect.android.app.R;
import it.geosolutions.geocollect.android.core.form.FormEditActivity;
import it.geosolutions.geocollect.android.core.login.LoginActivity;
import it.geosolutions.geocollect.android.core.login.LogoutActivity;
import it.geosolutions.geocollect.android.core.login.utils.LoginRequestInterceptor;
import it.geosolutions.geocollect.android.core.login.utils.NetworkUtil;
import it.geosolutions.geocollect.android.core.mission.utils.MissionUtils;
import it.geosolutions.geocollect.android.core.mission.utils.NavUtils;
import it.geosolutions.geocollect.android.core.mission.utils.PersistenceUtils;
import it.geosolutions.geocollect.android.core.mission.utils.SQLiteCascadeFeatureLoader;
import it.geosolutions.geocollect.android.core.mission.utils.SpatialiteUtils;
import it.geosolutions.geocollect.android.core.navigation.AbstractNavDrawerActivity;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerActivityConfiguration;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerAdapter;
import it.geosolutions.geocollect.android.core.navigation.NavDrawerItem;
import it.geosolutions.geocollect.android.map.GeoCollectMapActivity;
import it.geosolutions.geocollect.android.template.TemplateDownloadTask;
import it.geosolutions.geocollect.model.config.MissionTemplate;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import jonathanfinerty.once.Once;
import org.mapsforge.android.maps.MapActivity;
import org.mapsforge.android.maps.MapView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.newrelic.agent.android.NewRelic;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.AssetManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
/**
* An activity representing a list of Pending Missions. This activity has different presentations for handset and tablet-size devices. On handsets,
* the activity presents a list of items, which when touched, lead to a {@link PendingMissionDetailActivity} representing item details. On tablets,
* the activity presents the list of items and item details side-by-side using two vertical panes.
* <p>
* The activity makes heavy use of fragments. The list of items is a {@link PendingMissionListFragment} and the item details (if present) is a
* {@link PendingMissionDetailFragment}.
* <p>
* This activity also implements the required {@link PendingMissionListFragment.Callbacks} interface to listen for item selections.
*/
public class PendingMissionListActivity extends AbstractNavDrawerActivity implements
PendingMissionListFragment.Callbacks, MapActivity, LocationListener {
/**
* TAG for logging
*/
public static String TAG = "PendingMissionListActivity";
public static int SPATIAL_QUERY = 7001;
public static final String ARG_CREATE_MISSIONFEATURE = "CREATE_MISSIONFEATURE";
public static final String ARG_CREATING_TEMPLATE = "CREATING_MISSIONTEMPLATE";
public static final String PREFS_USES_DOWNLOADED_TEMPLATE = "USES_DOWNLOADED_TEMPLATE";
public static final String PREFS_DOWNLOADED_TEMPLATE_INDEX = "DOWNLOADED_TEMPLATE_INDEX";
public static final String PREFS_SELECTED_TEMPLATE_ID = "SELECTED_TEMPLATE_ID";
public static final String PREFS_START_WITH_MAP = "START_WITH_MAP";
public static final String UPDATE_MISSIONS = "UpdateMissionsPeriodically";
public static final int UPDATE_MISSIONS_TIME_AMOUNT = 30; // Minutes
public static final String CHECK_FOR_MAP_START = "CheckForMapStart";
private boolean shouldStartMap = false;
/**
* Contract key for map configuration
*/
public static String KEY_MAPSTARTLAT = "mapStartLat";
public static String KEY_MAPSTARTLON = "mapStartLon";
public static String KEY_MAPSTARTZOOM = "mapStartZoom";
public static String KEY_MAP_RESULT = "mapResult";
public static String KEY_NAVIGATING_UP = "navigatingUp";
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet device.
*/
private boolean mTwoPane;
/**
* Manage mapviews (two pane mode
*/
MapViewManager mapViewManager = new MapViewManager();
/**
* Spatialite Database for persistence
*/
public jsqlite.Database spatialiteDatabase;
private IntentFilter mIntentFilter;
private BroadcastReceiver mReceiver;
private static long LOCATION_MINTIME = 7 * 1000; // Minimum time interval for update in seconds, i.e. 5 seconds.
private static long LOCATION_MINDISTANCE = 10; // Minimum distance change for update in meters, i.e. 10 meters.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(BuildConfig.DEBUG){
Log.v(TAG, "onCreate()");
}
// Load the application properties file
Properties properties = new Properties();
try {
// access to the folder ‘assets’
AssetManager am = getAssets();
// opening the file
InputStream inputStream = am.open("geocollect.properties");
// loading of the properties
properties.load(inputStream);
} catch (IOException e) {
Log.e(GeoCollectApplication.class.getSimpleName(), e.toString());
}
// Get the NewRelic token, if found start the monitoring
String newRelicToken = properties.getProperty("newRelicToken");
if(newRelicToken != null){
NewRelic.withApplicationToken(newRelicToken).start(this);
}
// Login data is always necessary to load mission data
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
final String authKey = prefs.getString(LoginActivity.PREFS_AUTH_KEY, null);
if(
savedInstanceState == null &&
(getIntent() == null || !getIntent().hasExtra(KEY_NAVIGATING_UP)
)){
shouldStartMap = getStartAsMap();
}else{
shouldStartMap = false;
}
if (authKey == null) {
startActivityForResult(new Intent(this, LoginActivity.class),
LoginActivity.REQUEST_LOGIN);
shouldStartMap = false;
} else if (!Once.beenDone(TimeUnit.MINUTES, UPDATE_MISSIONS_TIME_AMOUNT, UPDATE_MISSIONS) && NetworkUtil.isOnline(getBaseContext())) {
if(BuildConfig.DEBUG){
Log.d(TAG, "fetching remote Templates");
}
final TemplateDownloadTask task = new TemplateDownloadTask() {
@Override
public void complete(final ArrayList<MissionTemplate> downloadedTemplates) {
/**
* download successful, elaborate result
**/
// 1. update database
ArrayList<MissionTemplate> validTemplates = new ArrayList<MissionTemplate>();
if (downloadedTemplates != null && downloadedTemplates.size() > 0) {
if (spatialiteDatabase == null) {
spatialiteDatabase = SpatialiteUtils.openSpatialiteDB(
PendingMissionListActivity.this, "geocollect/genova.sqlite");
}
for (MissionTemplate t : downloadedTemplates) {
if (!PersistenceUtils.createOrUpdateTablesForTemplate(t,
spatialiteDatabase)) {
Log.w(TAG, "error creating/updating table");
} else {
// if insert succesfull add to list of valid templates
validTemplates.add(t);
}
}
}
Log.d(TAG, "database updated");
// 2. save valid templates
PersistenceUtils.saveDownloadedTemplates(getBaseContext(), validTemplates);
if(BuildConfig.DEBUG){
Log.d(TAG, "valid templates persisted");
}
// 3. update navdrawer menu
runOnUiThread(new Runnable() {
@Override
public void run() {
navConf = getNavDrawerConfiguration();
mDrawerList.setAdapter(navConf.getBaseAdapter());
Log.d(TAG, "navdrawer updated");
}
});
Once.markDone(UPDATE_MISSIONS);
}
};
String username = prefs.getString(LoginActivity.PREFS_USER_EMAIL, null);
String password = prefs.getString(LoginActivity.PREFS_PASSWORD, null);
String authorizationString = LoginRequestInterceptor.getB64Auth(username, password);
task.execute(authKey, authorizationString);
}
// Default template
// Initialize database
// This should be the first thing the Activity does
if (spatialiteDatabase == null) {
spatialiteDatabase = SpatialiteUtils.openSpatialiteDB(this, "geocollect/genova.sqlite");
if (spatialiteDatabase != null && !spatialiteDatabase.dbversion().equals("unknown")) {
MissionTemplate t = MissionUtils.getDefaultTemplate(this);
if (!PersistenceUtils.createOrUpdateTablesForTemplate(t, spatialiteDatabase)) {
Log.e(TAG, "error creating/updating tables for " + t.nameField);
}
HashMap<String, ArrayList<String>> uploadables = PersistenceUtils.loadUploadables(this);
if (uploadables!= null && uploadables.size() > 0) {
PersistenceUtils.sanitizePendingFeaturesList(uploadables, spatialiteDatabase);
PersistenceUtils.saveUploadables(this, uploadables);
}
}
}
// Set the layout
getLayoutInflater().inflate(R.layout.activity_pendingmission_list,
(FrameLayout) findViewById(R.id.content_frame));
if (findViewById(R.id.pendingmission_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((PendingMissionListFragment) getSupportFragmentManager().findFragmentById(
R.id.pendingmission_list)).setActivateOnItemClick(true);
}
}
/**
* Callback method from {@link PendingMissionListFragment.Callbacks} indicating that the item with the given ID was selected.
*/
@Override
public void onItemSelected(Object obj) {
if(obj == null || !(obj instanceof MissionFeature)){
if(BuildConfig.DEBUG){
Log.w(TAG, "Tried to select an invalid object");
}
return;
}
MissionFeature selectedFeature = (MissionFeature) obj;
if (selectedFeature.typeName == null
|| !selectedFeature.typeName.endsWith(MissionTemplate.NEW_NOTICE_SUFFIX)) {
if (mTwoPane) {
// DELETE PREVIOUS MAP VIEWS
mapViewManager.destroyMapViews();
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(PendingMissionDetailFragment.ARG_ITEM_ID, selectedFeature.id);
arguments.putSerializable(PendingMissionDetailFragment.ARG_ITEM_FEATURE,selectedFeature);
PendingMissionDetailFragment fragment = new PendingMissionDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.pendingmission_detail_container, fragment).commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, PendingMissionDetailActivity.class);
detailIntent.putExtra(PendingMissionDetailFragment.ARG_ITEM_ID, selectedFeature.id);
detailIntent.putExtra(PendingMissionDetailFragment.ARG_ITEM_FEATURE, selectedFeature);
startActivity(detailIntent);
}
} else {
Log.d(TAG, "Clicked new feature with ID: " + selectedFeature.id);
Intent editIntent = new Intent(this, FormEditActivity.class);
editIntent.putExtra(ARG_CREATE_MISSIONFEATURE, true);
editIntent.putExtra(PendingMissionDetailFragment.ARG_ITEM_FEATURE, selectedFeature);
startActivity(editIntent);
}
}
/*
* (non-Javadoc)
*
* @see it.geosolutions.geocollect.android.core.navigation.AbstractNavDrawerActivity#getNavDrawerConfiguration()
*/
@Override
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;
}
@Override
protected void onNavItemSelected(int id) {
switch ((int) id) {
case 203:
final SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
final String user_email = prefs.getString(LoginActivity.PREFS_USER_EMAIL, null);
final String user_pw = prefs.getString(LoginActivity.PREFS_PASSWORD, null);
if (user_email != null && user_pw != null) {
// user is most likely logged in, show LogoutActivity
startActivityForResult(new Intent(this, LogoutActivity.class),
LogoutActivity.REQUEST_LOGOUT);
} else {
startActivity(new Intent(this, LoginActivity.class));
}
break;
// quit
case 204:
confirmExit();
break;
// logout
case 205:
confirmLogout();
break;
case 900:
startActivity(new Intent(this, CreditsActivity.class));
break;
default:
break;
}
// downloaded templates will have a dynamic id currently starting from 2000
if (id >= 2000) {
final ArrayList<MissionTemplate> downloadedTemplates = PersistenceUtils
.loadSavedTemplates(getBaseContext());
if(downloadedTemplates == null){
return;
}
final int index = id % 2000;
final int templateIndex = index ;
final MissionTemplate t = downloadedTemplates.get(templateIndex);
Log.d(TAG, "downloaded template "+ templateIndex + " selected : " + t.id);
clearDetailFragment();
Editor ed = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).edit();
ed.putBoolean(PREFS_USES_DOWNLOADED_TEMPLATE, true);
ed.putInt(PREFS_DOWNLOADED_TEMPLATE_INDEX, templateIndex);
ed.putString(PREFS_SELECTED_TEMPLATE_ID, t.id);
ed.commit();
((PendingMissionListFragment) getSupportFragmentManager().findFragmentById(
R.id.pendingmission_list)).setTemplate(t);
((GeoCollectApplication)getApplication()).setTemplate(t);
((PendingMissionListFragment) getSupportFragmentManager().findFragmentById(
R.id.pendingmission_list)).restartLoader(t.getLoaderIndex());
((PendingMissionListFragment) getSupportFragmentManager().findFragmentById(
R.id.pendingmission_list)).switchAdapter();
MissionUtils.checkMapStyles(getResources(), t);
}
}
/**
* removes the detailfragment in the twoPane layout, if necessary
*/
public void clearDetailFragment() {
if (mTwoPane) {
final PendingMissionDetailFragment fragment = (PendingMissionDetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.pendingmission_detail_container);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
}
}
/**
* Ask to confirm when exit
*/
@Override
public void onBackPressed() {
if (mTwoPane) {
final PendingMissionDetailFragment fragment = (PendingMissionDetailFragment) getSupportFragmentManager()
.findFragmentById(R.id.pendingmission_detail_container);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
// } else {
// confirmExit();
}
// } else {
// confirmExit();
}
}
public void confirmExit() {
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();
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
}).show();
}
/**
* Display a confirm prompt before logging out the user
*/
public void confirmLogout() {
new AlertDialog.Builder(this).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(getBaseContext()).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(getBaseContext(), getString(R.string.logout_logged_out),Toast.LENGTH_LONG).show();
startActivityForResult(
new Intent(getBaseContext(), LoginActivity.class),
LoginActivity.REQUEST_LOGIN);
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
}).show();
}
// **********************************************
// *********MAP VIEWS MANAGEMENT ***********
// **********************************************
/**
* @return a unique MapView ID on each call.
*/
public final int getMapViewId() {
if (this.mapViewManager == null) {
// registration auto creates mapViewManager
this.mapViewManager = new MapViewManager();
}
int i = this.mapViewManager.getMapViewId();
Log.v(TAG, "created mapview with id:" + i);
return i;
}
/**
* This method is called once by each MapView during its setup process.
*
* @param mapView the calling MapView.
*/
public final void registerMapView(MapView mapView) {
if (this.mapViewManager == null) {
// registration auto creates mapViewManager
this.mapViewManager = new MapViewManager();
}
this.mapViewManager.registerMapView(mapView);
}
public Context getActivityContext() {
return this;
}
@Override
protected void onDestroy() {
super.onDestroy();
// In the tablet layout the map can be visible within this activity
if (this.mapViewManager != null) {
this.mapViewManager.destroyMapViews();
}
if (this.spatialiteDatabase != null) {
try {
this.spatialiteDatabase.close();
Log.v(TAG, "Spatialite Database Closed");
} catch (jsqlite.Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
}
/**
* Since the triggering intent is launched by the activity and not bay a Fragment the child Fragments will not receive the result We override the
* default onActivityResult() to propagate the result to the child Fragments
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
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 == PendingMissionListActivity.SPATIAL_QUERY){
shouldStartMap = false;
if(data != null && data.hasExtra(KEY_MAP_RESULT)){
onNavItemSelected(data.getIntExtra(KEY_MAP_RESULT, 900));
return;
}
}
navConf = getNavDrawerConfiguration();
mDrawerList.setAdapter(navConf.getBaseAdapter());
Log.d(TAG, "navdrawer updated");
navConf.getBaseAdapter().notifyDataSetChanged();
// We need to explicitly call the child Fragments onActivityResult()
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
try {
fragment.onActivityResult(requestCode, resultCode, data);
}catch (NullPointerException npe){
// TODO This is ABS bug, need to switch to ActionBarCompat
Log.e(TAG, npe.getLocalizedMessage(), npe);
}
}
}
/**
* Launches the Map activity
*/
public void launchFullMap() {
// setup map options
// TODO parametrize it
Intent launch = new Intent(this, GeoCollectMapActivity.class);
launch.setAction(Intent.ACTION_VIEW);
launch.putExtra(MapsActivity.PARAMETERS.CONFIRM_ON_EXIT, false);
// ArrayList<Layer> layers = (ArrayList<Layer>) LocalPersistence.readObjectFromFile(this, LocalPersistence.CURRENT_MAP);
// if(layers == null || layers.isEmpty()){
MissionTemplate t = ((PendingMissionListFragment) getSupportFragmentManager()
.findFragmentById(R.id.pendingmission_list)).getCurrentMissionTemplate();
MSMMap m = SpatialDbUtils.mapFromDb();
ArrayList<String> bg_layers = null;
try{
if(t.config != null && t.config.get(MissionTemplate.BG_LAYERS_KEY) != null){
if(t.config.get(MissionTemplate.BG_LAYERS_KEY) instanceof ArrayList<?>){
bg_layers = (ArrayList<String>) t.config.get(MissionTemplate.BG_LAYERS_KEY);
}
}
}catch (ClassCastException cce){
if(BuildConfig.DEBUG){
Log.w(TAG, "backgroundLayers tag is not an ArrayList, ignoring");
}
bg_layers = null;
}
// Use only the layers that are related to this Mission
ArrayList<Layer> layersList = new ArrayList<Layer>();
Layer layer = null;
for (Iterator<Layer> it = m.layers.iterator(); it.hasNext();) {
layer = it.next();
if (layer.getTitle().equals(t.schema_seg.localSourceStore)
|| layer.getTitle().equals(t.schema_sop.localFormStore)
|| layer.getTitle().equals(t.schema_seg.localSourceStore + MissionTemplate.NEW_NOTICE_SUFFIX)
) {
layersList.add(layer);
}else if (bg_layers != null && bg_layers.contains(layer.getTitle())){
// Adding in the head position, so the layer will
// be on the last in the LayerSwitcher order
layersList.add(0, layer);
}
}
// Set the correct layers
m.layers = layersList;
// Set map configurations, if available
if(t.config != null){
if(t.config.get(KEY_MAPSTARTLAT) != null){
try {
double mapStartLat = Double.parseDouble((String) t.config.get(KEY_MAPSTARTLAT));
launch.putExtra(MapsActivity.PARAMETERS.LAT, mapStartLat);
} catch (NumberFormatException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
if(t.config.get(KEY_MAPSTARTLON) != null){
try {
double mapStartLon = Double.parseDouble((String) t.config.get(KEY_MAPSTARTLON));
launch.putExtra(MapsActivity.PARAMETERS.LON, mapStartLon);
} catch (NumberFormatException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
if(t.config.get(KEY_MAPSTARTZOOM) != null){
try {
int mapStartZoom = Integer.parseInt((String) t.config.get(KEY_MAPSTARTZOOM));
launch.putExtra(MapsActivity.PARAMETERS.ZOOM_LEVEL, (byte) mapStartZoom);
} catch (NumberFormatException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
}
launch.putExtra(MapsActivity.PARAMETERS.ZOOM_LEVEL_MIN, (byte) 11);
launch.putExtra(MapsActivity.PARAMETERS.ZOOM_LEVEL_MAX, (byte) 22);
launch.putExtra(MapsActivity.MSM_MAP, m);
// select here a drawer mode
launch.putExtra(MapsActivity.PARAMETERS.DRAWER_MODE, DrawerMode.ONLY_LEFT.ordinal());
// }
startActivityForResult(launch, SPATIAL_QUERY);
}
public void checkGPSandStartCreation(View v){
checkGPSandStartCreation(this);
}
public static void checkGPSandStartCreation(final SherlockFragmentActivity abs_activity) {
if (!isGPSAvailable(abs_activity)) {
new AlertDialog.Builder(abs_activity).setTitle(R.string.app_name).setMessage(R.string.gps_not_enabled)
.setPositiveButton(R.string.open_gps_settings, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
abs_activity.startActivityForResult(new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), PendingMissionListFragment.ARG_ENABLE_GPS);
}
}).setNegativeButton(R.string.not_now, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
startMissionFeatureCreation(abs_activity);
}
}).show();
} else {
startMissionFeatureCreation(abs_activity);
}
}
/**
* checks if location services are available
*/
public static boolean isGPSAvailable(Context context) {
if(context==null){
return false;
}
LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return manager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
/**
* starts the {@link MissionFeature} creation
*/
public static void startMissionFeatureCreation(SherlockFragmentActivity abs_activity) {
Intent i = new Intent(abs_activity, FormEditActivity.class);
i.putExtra(PendingMissionListActivity.ARG_CREATE_MISSIONFEATURE, true);
abs_activity.startActivityForResult(i, FormEditActivity.FORM_CREATE_NEW_MISSIONFEATURE);
}
@Override
public void onLocationChanged(Location location) {
Log.v(TAG, "Location: \n lat "+location.getLatitude()+"\n lon "+location.getLongitude());
SharedPreferences sp = getSharedPreferences(SQLiteCascadeFeatureLoader.PREF_NAME,Context.MODE_PRIVATE);
// If it is the first time we get a Location, and the list is ordered by distance, refresh the list automatically
boolean needRefresh = sp.getBoolean(SQLiteCascadeFeatureLoader.ORDER_BY_DISTANCE, false)
&& ( !sp.contains(SQLiteCascadeFeatureLoader.LOCATION_X)
|| sp.getLong(SQLiteCascadeFeatureLoader.LOCATION_X, 0) == 0);
SharedPreferences.Editor editor = sp.edit();
// Set position
editor.putLong(SQLiteCascadeFeatureLoader.LOCATION_X, Double.doubleToRawLongBits(location.getLongitude()));
editor.putLong(SQLiteCascadeFeatureLoader.LOCATION_Y, Double.doubleToRawLongBits(location.getLatitude()));
editor.apply();
if(needRefresh){
PendingMissionListFragment listFragment = ((PendingMissionListFragment) getSupportFragmentManager().findFragmentById(
R.id.pendingmission_list));
if(listFragment != null){
listFragment.onRefresh();
}
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
//Log.d("PMLA", "Status Changed - Provider: " + provider +" Status: "+status);
}
@Override
public void onProviderEnabled(String provider) {
//Log.d("PMLA", "Provider Enabled: " + provider );
}
@Override
public void onProviderDisabled(String provider) {
//Log.d("PMLA", "Provider Enabled: " + provider );
}
/**
* Get provider name.
* @return Name of best suiting provider.
* */
String getProviderName() {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setPowerRequirement(Criteria.POWER_LOW); // Chose your desired power consumption level.
criteria.setAccuracy(Criteria.ACCURACY_FINE); // Choose your accuracy requirement.
criteria.setSpeedRequired(false); // Chose if speed for first location fix is required.
criteria.setAltitudeRequired(false); // Choose if you use altitude.
criteria.setBearingRequired(false); // Choose if you use bearing.
criteria.setCostAllowed(false); // Choose if this provider can waste money :-)
// Provide your criteria and flag enabledOnly that tells
// LocationManager only to return active providers.
return locationManager.getBestProvider(criteria, true);
}
@Override
protected void onResume() {
super.onResume();
if(mIntentFilter == null){
mIntentFilter=new IntentFilter("android.location.PROVIDERS_CHANGED");
}
if(mReceiver == null){
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
LocationManager locationManager = (LocationManager) PendingMissionListActivity.this.getSystemService(Context.LOCATION_SERVICE);
if(locationManager != null){
locationManager.requestLocationUpdates(getProviderName(), LOCATION_MINTIME, LOCATION_MINDISTANCE, PendingMissionListActivity.this);
}
}
};
}
registerReceiver(mReceiver, mIntentFilter);
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if(locationManager != null){
locationManager.requestLocationUpdates(getProviderName(), LOCATION_MINTIME, LOCATION_MINDISTANCE, this);
}
if(shouldStartMap){
launchFullMap();
}
}
@Override
protected void onPause() {
super.onPause();
if(mReceiver != null){
unregisterReceiver(mReceiver);
}
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if(locationManager != null){
locationManager.removeUpdates(this);
}
}
/**
* Get the preference for the starting Activity
* - TRUE: start with map
* - FALSE: start with list
* @return boolean
*/
public boolean getStartAsMap(){
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
try {
return sp.getBoolean(PendingMissionListActivity.PREFS_START_WITH_MAP, false);
}catch(ClassCastException cce){
return false;
}
}
}