package de.apps4ics.mountainnavigation;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.ActionBar;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import com.survivingwithandroid.weather.lib.WeatherClient;
import com.survivingwithandroid.weather.lib.WeatherCode;
import com.survivingwithandroid.weather.lib.WeatherConfig;
import com.survivingwithandroid.weather.lib.exception.WeatherLibException;
import com.survivingwithandroid.weather.lib.exception.WeatherProviderInstantiationException;
import com.survivingwithandroid.weather.lib.model.DayForecast;
import com.survivingwithandroid.weather.lib.model.HistoricalWeather;
import com.survivingwithandroid.weather.lib.model.Weather;
import com.survivingwithandroid.weather.lib.model.WeatherForecast;
import com.survivingwithandroid.weather.lib.provider.openweathermap.OpenweathermapProviderType;
import com.survivingwithandroid.weather.lib.request.WeatherRequest;
import org.osmdroid.api.IMapController;
import org.osmdroid.bonuspack.location.NominatimPOIProvider;
import org.osmdroid.bonuspack.location.POI;
import org.osmdroid.bonuspack.overlays.MapEventsOverlay;
import org.osmdroid.bonuspack.overlays.MapEventsReceiver;
import org.osmdroid.bonuspack.overlays.Marker;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.OverlayItem;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import de.apps4ics.mountainnavigation.pois.AddBreakpointDialog;
import de.apps4ics.mountainnavigation.pois.AddFountainDialog;
import de.apps4ics.mountainnavigation.pois.AddHutDialog;
import de.apps4ics.mountainnavigation.pois.AddPathDialog;
import de.apps4ics.mountainnavigation.pois.AddPeakDialog;
import de.apps4ics.mountainnavigation.pois.CellReception;
import de.apps4ics.mountainnavigation.pois.DbGeoPoint;
import de.apps4ics.mountainnavigation.pois.Fountain;
import de.apps4ics.mountainnavigation.pois.Image;
import de.apps4ics.mountainnavigation.pois.Lift;
import de.apps4ics.mountainnavigation.pois.Path;
import de.apps4ics.mountainnavigation.pois.Poi;
import de.apps4ics.mountainnavigation.pois.TrashBin;
import de.apps4ics.mountainnavigation.pois.Wifi;
public class MainActivity extends AppCompatActivity implements LocationListener {
public static final String TAG = "MountainNavigation";
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private CharSequence mTitle;
private CharSequence mDrawerTitle;
private static final int GPS_MIN_TIME = 5000;
private static final int GPS_MIN_DIST = 5;
private static final String API_KEY = "fd4034defae557fd5f2fdaaf73c3402c";
private static ConnectivityManager cm;
private static TelephonyManager tm;
private static WifiManager wm;
private static NetworkInfo activeNetwork;
private static int networkStrength;
private static final int MAX_WIFI_LEVELS = 5;
public static final long VIB_LENGTH = 50;
public final static int SELECT_POI_PHOTO = 1;
private static SimpleDateFormat df_hm;
private static SimpleDateFormat df_full;
private Resources res;
private FloatingActionButton fab;
private Weather todaysWeather;
private Weather tomorrowsWeather;
private HistoricalWeather histWeather;
private DayForecast todaysForecast;
private DayForecast tomorrowsForecast;
private WeatherClient weatherClient;
private static Integer[] severeWeatherCodes;
private static float minHotTemp;
private static float maxColdTemp;
private static float minWindySpeed;
private boolean showWeatherHints;
private DatabaseHandler dbHandler;
private MapView mapView;
private IMapController mapController;
private int ZOOM_LEVEL;
private ActionBarDrawerToggle drawerToggle;
private String[] fountainSizes;
private String[] pathOptions;
private String[] pathDescs;
private Integer[] pathOptionImgs;
private String[] hutTypes;
private String[] breakPointOptions;
private Integer[] breakPointOptionsImgs;
private String[] entries;
private Integer[] entryImgs;
private Integer[] fountainImgs;
private DrawerLayout drawerLayout;
private ListView listView;
private List<Marker>[] poiMarkers;
private Map<String, List<POI>> pois;
protected static ArrayList<OverlayItem> pathMarkers;
protected static OverlayItem imageMarker;
private String provider;
private Location mLocation;
private LocationManager locationManager;
private List<Location> foundLocations;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
res = getResources();
pathMarkers = new ArrayList<>();
cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
activeNetwork = cm.getActiveNetworkInfo();
networkStrength = 0;
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
wm = (WifiManager) getSystemService(WIFI_SERVICE);
df_hm = new SimpleDateFormat(res.getString(R.string.date_format_hm));
df_full = new SimpleDateFormat(res.getString(R.string.date_format_full));
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.container);
dbHandler = new DatabaseHandler(this);
ZOOM_LEVEL = 18;
mapView = new MapView(getApplicationContext());
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
mapController = mapView.getController();
mapController.setZoom(ZOOM_LEVEL);
mapController.setCenter(new GeoPoint(48.52, 9.055));
poiMarkers = new ArrayList[Types.SIZE];
for(int i=0; i<poiMarkers.length; ++i){
poiMarkers[i] = new ArrayList<>();
}
foundLocations = new ArrayList<>();
relativeLayout.addView(mapView);
mTitle = mDrawerTitle = getTitle();
initGps();
fountainSizes = res.getStringArray(R.array.fountain_size_dialog_options);
fountainImgs = new Integer[]{
R.drawable.fountain_size_small,
R.drawable.fountain_size_medium,
R.drawable.fountain_size_big,
};
pathDescs = res.getStringArray(R.array.path_dialog_descs);
pathOptions = res.getStringArray(R.array.path_dialog_options);
pathOptionImgs = new Integer[]{
R.mipmap.path_exposed,
R.mipmap.path_difficult_wet,
R.mipmap.path_giddiness,
R.mipmap.path_climbing
};
hutTypes = res.getStringArray(R.array.hut_dialog_types);
breakPointOptions = res.getStringArray(R.array.break_point_dialog_options);
breakPointOptionsImgs = new Integer[]{
R.mipmap.ic_rock,
R.mipmap.ic_bench,
R.mipmap.ic_table,
R.mipmap.ic_roofed
};
entries = res.getStringArray(R.array.toggleEntries);
entryImgs = new Integer[]{
R.drawable.water,
R.drawable.path,
R.mipmap.ic_cabin,
R.mipmap.path_exposed,
R.drawable.break_point,
R.drawable.trash,
R.drawable.image_upload,
R.drawable.cell_reception,
R.drawable.wifi,
R.drawable.lift
};
WeatherClient.ClientBuilder weatherBuilder = new WeatherClient.ClientBuilder();
WeatherConfig weatherConfig = new WeatherConfig();
weatherConfig.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
weatherConfig.ApiKey = API_KEY;
weatherConfig.lang = res.getString(R.string.lang_identifier);
weatherConfig.numDays = 2;
minWindySpeed = 8; //http://www.wettergefahren-fruehwarnung.de/Artikel/beaufort.html
if(weatherConfig.unitSystem.equals(WeatherConfig.UNIT_SYSTEM.I)){
minHotTemp = 86; //about 30 degree celsius
maxColdTemp = 50; //about 10 degree celsius
} else {
minHotTemp = 30;
maxColdTemp = 10;
}
showWeatherHints = true;
//TODO split into severe weather and foggy, windy, sunny, ...
severeWeatherCodes = new Integer[]{
WeatherCode.TORNADO.getCode(),
WeatherCode.TROPICAL_STORM.getCode(),
WeatherCode.HURRICANE.getCode(),
WeatherCode.SEVERE_THUNDERSTORMS.getCode(),
WeatherCode.THUNDERSTORMS.getCode(),
WeatherCode.MIXED_RAIN_SNOW.getCode(),
WeatherCode.MIXED_RAIN_SLEET.getCode(),
WeatherCode.MIXED_SNOW_SLEET.getCode(),
WeatherCode.FREEZING_DRIZZLE.getCode(),
WeatherCode.FREEZING_RAIN.getCode(),
WeatherCode.HEAVY_SHOWERS.getCode(),
WeatherCode.SNOW_FLURRIES.getCode(),
WeatherCode.LIGHT_SNOW_SHOWERS.getCode(),
WeatherCode.BLOWING_SNOW.getCode(),
WeatherCode.SNOW.getCode(),
WeatherCode.HAIL.getCode(),
WeatherCode.SLEET.getCode(),
WeatherCode.FOGGY.getCode(),
WeatherCode.HAZE.getCode(),
WeatherCode.WINDY.getCode(),
WeatherCode.COLD.getCode(),
WeatherCode.SUNNY.getCode(),
WeatherCode.MIXED_RAIN_AND_HAIL.getCode(),
WeatherCode.ISOLATED_THUNDERSTORMS.getCode(),
WeatherCode.SCATTERED_THUNDERSTORMS.getCode(),
WeatherCode.HEAVY_SNOW.getCode(),
WeatherCode.SCATTERED_SNOW_SHOWERS.getCode(),
WeatherCode.THUNDERSHOWERS.getCode(),
WeatherCode.SNOW_SHOWERS.getCode(),
WeatherCode.ISOLATED_THUDERSHOWERS.getCode(),
WeatherCode.TORNADO.getCode()
};
weatherClient = null;
try {
weatherClient = weatherBuilder.attach(getApplicationContext())
.provider(new OpenweathermapProviderType())
.httpClient(com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient.class)
.config(weatherConfig)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mLocation == null){
InformDialog informDialog = new InformDialog(getString(R.string.inform_title), getString(R.string.inform_gps_pos_not_found));
informDialog.show(getFragmentManager(), "Inform Dialog");
return;
}
AddPoiDialog addPoiDialog = new AddPoiDialog();
addPoiDialog.show(getFragmentManager(), "Add POI Dialog");
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
listView = (ListView) findViewById(R.id.navigation_drawer);
drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// listView.setItemsCanFocus(false);
ImageListAdapter adapter = new ImageListAdapter(MainActivity.this, entries, entryImgs, false);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TableLayout layout = (TableLayout) view;
toggleDrawerItems(layout, position);
}
});
drawerLayout.setDrawerListener(drawerToggle);
double _lat = 48.52;
double _lon = 9.055;
double _alt = 350;
long _time = System.currentTimeMillis() / 1000;
DbGeoPoint dbgp = new DbGeoPoint(_lat, _lon, _alt, _time);
long gp_id = dbHandler.addPoi(dbgp);
dbgp.setId(gp_id);
Fountain fountain = new Fountain(0, 2, dbgp);
long f_id = dbHandler.addPoi(fountain);
}
private void toggleDrawerItems(TableLayout layout, int position){
TableRow tr = (TableRow) layout.getChildAt(0); //TODO is tablerow?
TextView tv = null;
ImageView iv = null;
for(int i=0; i<tr.getChildCount(); ++i){
View v = tr.getChildAt(i);
try {
tv = (TextView) v;
} catch(ClassCastException cce){
//Log.e(TAG, "Could not cast " + v.getClass().toString() + " to TextView!");
}
try {
iv = (ImageView) v;
} catch(ClassCastException cce){
//Log.e(TAG, "Could not cast " + v.getClass().toString() + " to ImageView!");
}
}
if(tv == null || iv == null){
Log.e(TAG, "Neither TextView nor ImageView can be null!");
return;
}
int type = getType(position);
if(iv.getTag() == null || iv.getTag() == "disabled"){
iv.setColorFilter(null);
iv.setTag("");
tv.setTextColor(res.getColor(R.color.text_color_selected));
String title = entries[position];
List<Poi> tempPoiList = dbHandler.getPoiByType(type);
UpdatePoiIconsAsyncTask asyncTask = new UpdatePoiIconsAsyncTask(type, title);
poiMarkers[type] = asyncTask.doInBackground(tempPoiList);
mapView.getOverlays().addAll(poiMarkers[type]);
mapView.invalidate();
} else {
iv.setColorFilter(res.getColor(R.color.icon_unselected_gray));
iv.setTag("disabled");
tv.setTextColor(res.getColor(R.color.text_color));
Toaster("You disabled " + entries[position]);
for(int i=0; i<poiMarkers[type].size(); ++i){
Overlay poi = poiMarkers[type].get(i);
mapView.getOverlays().remove(poi);
}
poiMarkers[type] = new ArrayList<>();
mapView.invalidate();
}
}
private class UpdatePoiIconsAsyncTask extends AsyncTask<List<Poi>, Void, List<Marker>> {
int type;
String title;
public UpdatePoiIconsAsyncTask(int type, String title){
this.type = type;
this.title = title;
}
@Override
protected List<Marker> doInBackground(List<Poi>... params) {
//TODO get weather and rate POIs (if sunny, smaller fountains, ...)
List<Marker> result = new ArrayList<>();
List<Poi> tempPoiList = params[0]; //This is only one list
for(int i=0; i<tempPoiList.size(); ++i){
Poi poi = tempPoiList.get(i);
DbGeoPoint dbgp = poi.getGp();
GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
String titleText = title;
String snippetText = res.getString(R.string.osm_marker_snippet, gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), df_full.format(new Date(dbgp.getTime())));
switch(type){
case Types.FOUNTAIN:
titleText += " (" + fountainSizes[((Fountain) poi).getSize()] + ")";
break;
case Types.PATH: {
Path p = (Path) poi;
DbGeoPoint pathEnd = p.getEndGp();
titleText += " (" + p.getLength() + ")";
snippetText += "\n";
snippetText += "Exposed: " + ((p.getExposed() == 1) ? "Yes!" : "No!");
snippetText += "\n";
snippetText += "Difficult: " + ((p.getDiffWet() == 1) ? "Yes!" : "No!");
snippetText += "\n";
snippetText += "Giddiness: " + ((p.getGiddiness() == 1) ? "Yes!" : "No!");
snippetText += "\n";
snippetText += "Climbing: " + ((p.getClimbing() == 1) ? "Yes!" : "No!");
Marker positionMarker = new Marker(mapView);
positionMarker.setPosition(new GeoPoint(pathEnd.getLat(), pathEnd.getLon(), pathEnd.getAlt()));
positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
positionMarker.setTitle(titleText);
positionMarker.setSnippet(snippetText);
positionMarker.setImage(res.getDrawable(entryImgs[getPos(type)]));
Drawable[] iconLayer = new Drawable[2];
iconLayer[0] = res.getDrawable(R.mipmap.ic_poi);
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(entryImgs[getPos(type)]);
if(bd == null) continue;
Bitmap b = bd.getBitmap();
Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
bd = new BitmapDrawable(res, bResized);
bd.setGravity(Gravity.CENTER_HORIZONTAL);
iconLayer[1] = bd;
LayerDrawable icon = new LayerDrawable(iconLayer);
positionMarker.setIcon(icon);
result.add(positionMarker);
poiMarkers[getPos(type)].add(positionMarker);
}
break;
}
Marker positionMarker = new Marker(mapView);
positionMarker.setPosition(gp);
positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
positionMarker.setTitle(titleText);
positionMarker.setSnippet(snippetText);
positionMarker.setImage(res.getDrawable(entryImgs[getPos(type)]));
Drawable[] iconLayer = new Drawable[2];
iconLayer[0] = res.getDrawable(R.mipmap.ic_poi);
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(entryImgs[getPos(type)]);
if(bd == null) continue;
Bitmap b = bd.getBitmap();
Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
bd = new BitmapDrawable(res, bResized);
bd.setGravity(Gravity.CENTER_HORIZONTAL);
iconLayer[1] = bd;
LayerDrawable icon = new LayerDrawable(iconLayer);
positionMarker.setIcon(icon);
result.add(positionMarker);
poiMarkers[getPos(type)].add(positionMarker);
}
return result;
}
}
private int getPos(int type){
int pos;
switch(type){
case Types.FOUNTAIN:
pos = 0;
break;
case Types.PATH:
pos = 1;
break;
case Types.HUT:
pos = 2;
break;
case Types.PEAK:
pos = 3;
break;
case Types.BREAK_POINT:
pos = 4;
break;
case Types.TRASH_BIN:
pos = 5;
break;
case Types.PIC:
pos = 6;
break;
case Types.CELL_RECEPTION:
pos = 7;
break;
case Types.WIFI:
pos = 8;
break;
case Types.LIFT:
pos = 9;
break;
default:
pos = 0;
break;
}
return pos;
}
private int getType(int position){
int type;
switch (position){
case 0:
type = Types.FOUNTAIN;
break;
case 1:
type = Types.PATH;
break;
case 2:
type = Types.HUT;
break;
case 3:
type = Types.PEAK;
break;
case 4:
type = Types.BREAK_POINT;
break;
case 5:
type = Types.TRASH_BIN;
break;
case 6:
type = Types.PIC;
break;
case 7:
type = Types.CELL_RECEPTION;
break;
case 8:
type = Types.WIFI;
break;
case 9:
type = Types.LIFT;
break;
case 10:
type = Types.GP;
break;
default:
type = 0;
break;
}
return type;
}
private String getTypeName(int type){
String name = "";
switch(type){
case Types.FOUNTAIN:
name = "fountain";
break;
case Types.PATH:
name = "path";
break;
case Types.HUT:
name = "hut";
break;
case Types.PEAK:
name = "peak";
break;
case Types.BREAK_POINT:
name = "break_point";
break;
case Types.TRASH_BIN:
name = "trash_bin";
break;
case Types.PIC:
name = "image";
break;
case Types.CELL_RECEPTION:
name = "cell_reception";
break;
case Types.WIFI:
name = "wifi";
break;
case Types.LIFT:
name = "lift";
break;
}
return name;
}
private void initGps(){
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean isLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(!isLocationEnabled){
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
mLocation = locationManager.getLastKnownLocation(provider);
}
private void Toaster(String text){
Toaster(text, false);
}
private void Toaster(String text, boolean longDuration){
if(longDuration) Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
else Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
public String[] getBreakPointOptions(){
return breakPointOptions;
}
public Integer[] getBreakPointOptionsImgs(){
return breakPointOptionsImgs;
}
public MapView getMapView(){
return mapView;
}
public DatabaseHandler getDbHandler(){
return dbHandler;
}
public ArrayList<OverlayItem> getPathMarkers(){
return pathMarkers;
}
public void setPathMarkers(ArrayList<OverlayItem> al){
pathMarkers = al;
}
public String[] getFountainSizes(){
return fountainSizes;
}
public Integer[] getFountainImgs(){
return fountainImgs;
}
public String[] getPathOptions(){
return pathOptions;
}
public String[] getPathDescs(){
return pathDescs;
}
public Integer[] getPathOptionImgs(){
return pathOptionImgs;
}
private void setActiveNetwork(){
activeNetwork = cm.getActiveNetworkInfo();
}
public static void setNetworkStrength(int strength){
networkStrength = strength;
}
private void addSimpleMarker(GeoPoint gp){
Marker positionMarker = new Marker(mapView);
positionMarker.setPosition(gp);
positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
positionMarker.setTitle(getString(R.string.osm_marker_title));
positionMarker.setSnippet("Latitude: " + gp.getLatitude() + "\n" + "Longitude: " + gp.getLongitude());
mapView.getOverlays().add(positionMarker);
mapView.invalidate();
}
private void updatePois() {
pois = new HashMap<>();
pois.put("path", new ArrayList<POI>());
pois.put("spring", new ArrayList<POI>());
pois.put("stream", new ArrayList<POI>());
pois.put("peak", new ArrayList<POI>());
pois.put("wilderness_hut", new ArrayList<POI>());
pois.put("alpine_hut", new ArrayList<POI>());
pois.put("water", new ArrayList<POI>());
pois.put("aerialway", new ArrayList<POI>());
Iterator it = pois.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<String, List> entry = (Map.Entry<String, List>) it.next();
new GetPoiFromOsm().execute(entry.getKey());
}
}
@Override
public void onLocationChanged(Location location) {
mLocation = location;
if(mLocation == null) return;
foundLocations.add(location);
updatePois();
double lat = location.getLatitude();
double lon = location.getLongitude();
GeoPoint gp = new GeoPoint(lat, lon);
addSimpleMarker(gp);
mapController.setCenter(gp);
//TODO Move this to the not-yet-implemented upload method
weatherClient.getForecastWeather(new WeatherRequest(lon, lat), new WeatherClient.ForecastWeatherEventListener() {
@Override
public void onWeatherRetrieved(WeatherForecast forecast) {
todaysForecast = forecast.getForecast(0);
tomorrowsForecast = forecast.getForecast(1);
todaysWeather = todaysForecast.weather;
tomorrowsWeather = tomorrowsForecast.weather;
Log.d(TAG, "City [" + todaysWeather.location.getCity() + "] Current temp: " + todaysWeather.temperature.getTemp());
String title = String.format("Weather for %s in %s", todaysWeather.location.getCity(), todaysWeather.location.getCountry());
String msg = String.format("%1$.1f%2$s (%3$.1f%4$s/%5$.1f%6$s)\nSunrise: %7$s\nSunset: %8$s\nWeatherCode: %9$d\nWeatherId: %10$d",
todaysForecast.forecastTemp.day,
forecast.getUnit().tempUnit,
todaysForecast.forecastTemp.min,
forecast.getUnit().tempUnit,
todaysForecast.forecastTemp.max,
forecast.getUnit().tempUnit,
df_hm.format(new Date(todaysWeather.location.getSunrise() * 1000)),
df_hm.format(new Date(todaysWeather.location.getSunset() * 1000)),
todaysWeather.currentCondition.getWeatherCode().getCode(),
todaysWeather.currentCondition.getWeatherId());
//InformDialog informWeatherDialog = new InformDialog(title, msg);
//informWeatherDialog.show(getFragmentManager(), "Inform Dialog");
boolean isSevereWeather = isSevereWeather(todaysWeather.currentCondition.getWeatherCode().getCode());
Log.d(TAG, title + ": " + msg);
Log.d(TAG, "isSevereWeather? " + isSevereWeather);
//TODO add more hints
if (showWeatherHints) {
List<String> titles = new ArrayList<>();
List<String> descs = new ArrayList<>();
if (isSunny()) {
titles.add("Sunny");
descs.add("The weather might be sunny. You should take some suncream with you!");
}
if (isHot()) {
titles.add("Hot");
descs.add("It is hot outside. Remember to take enough to drink with you.");
}
if (isCold()) {
titles.add("Cold");
descs.add("The weather might be cold. You should take some warm clothes with you!");
}
if (isWindy()) {
titles.add("Windy");
descs.add("The weather might be windy. You should take some windproof clothes with you!");
}
if (isAfterSunset()) {
titles.add("Sunset");
descs.add("It is already after sunset. Better take a head lamp with you.");
}
if (titles.size() > 0 && descs.size() > 0) {
String[] titleArr = new String[titles.size()];
String[] descArr = new String[descs.size()];
titleArr = titles.toArray(titleArr);
descArr = descs.toArray(descArr);
WarningListAdapter warningAdapter = new WarningListAdapter(MainActivity.this, titleArr, descArr);
InformListDialog weatherHintDialog = new InformListDialog("Hints", warningAdapter);
weatherHintDialog.show(getFragmentManager(), "Warning Hint Dialog");
}
}
if (isSevereWeather) {
String warnMsg = "The weather around you in " + todaysWeather.location.getCity() + " is '" + todaysWeather.currentCondition.getWeatherCode().getLabel(getApplicationContext()) + "'!";
InformDialog informAlertDialog = new InformDialog("Weather Warning!", warnMsg);
informAlertDialog.show(getFragmentManager(), "Inform Dialog - Weather Warning");
}
}
@Override
public void onWeatherError(WeatherLibException wle) {
Log.e(TAG, "Weather error - parsing data");
wle.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
Log.e(TAG, "Connection Error");
t.printStackTrace();
}
});
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged: " + provider + ", " + status);
}
@Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "onProviderDisabled: " + provider);
}
private boolean isSevereWeather(int weatherCode){
return Arrays.asList(severeWeatherCodes).contains(weatherCode);
}
private boolean isAfterSunset(){
return isAfterSunset(System.currentTimeMillis());
}
private boolean isAfterSunset(long time){
return time > (todaysWeather.location.getSunset() * 1000) && time < (tomorrowsWeather.location.getSunrise() * 1000);
}
private boolean isHot(){
return todaysWeather.currentCondition.getWeatherCode().getCode() == WeatherCode.SUNNY.getCode() ||
(todaysWeather.temperature.getTemp() >= minHotTemp || todaysWeather.temperature.getMaxTemp() >= minHotTemp);
}
private boolean isSunny(){
return todaysWeather.currentCondition.getWeatherCode().getCode() == WeatherCode.SUNNY.getCode();
}
private boolean isCold(){
return todaysWeather.currentCondition.getWeatherCode().getCode() == WeatherCode.COLD.getCode() ||
(todaysWeather.temperature.getTemp() <= maxColdTemp || todaysWeather.temperature.getMinTemp() <= maxColdTemp);
}
private boolean isWindy(){
return todaysWeather.currentCondition.getWeatherCode().getCode() == WeatherCode.WINDY.getCode() ||
(todaysWeather.wind.getSpeed() >= minWindySpeed);
}
private boolean isDark(long length){
return isDark(System.currentTimeMillis(), length);
}
private boolean isDark(long time, long length){
return isAfterSunset(time) || isAfterSunset(time + length);
}
private HistoricalWeather getWeather(float lat, float lon, long start, long end){
Date startDate = new Date(start / 1000); //OWM uses seconds instead of milliseconds
Date endDate = new Date(end / 1000);
histWeather = null;
weatherClient.getHistoricalWeather(new WeatherRequest(lon, lat), startDate, endDate, new WeatherClient.HistoricalWeatherEventListener() {
@Override
public void onWeatherRetrieved(HistoricalWeather historicalWeather) {
//TODO check if it was sunny/rainy and set fountain options based on this
histWeather = historicalWeather;
}
@Override
public void onWeatherError(WeatherLibException wle) {
Log.e(TAG, "Weather error - parsing data");
wle.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
Log.e(TAG, "Connection Error");
t.printStackTrace();
}
});
return histWeather;
}
public class InformDialog extends DialogFragment {
private String title;
private String msg;
public InformDialog(String title, String msg){
this.title = title;
this.msg = msg;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title)
.setMessage(msg)
.setCancelable(false)
//.setIcon(res.getDrawable(R.mipmap.ic_info_icon))
.setPositiveButton(R.string.inform_positive_button, null);
return builder.create();
}
}
public class InformListDialog extends DialogFragment {
private String title;
private ListAdapter adapter;
public InformListDialog(String title, ListAdapter adapter){
this.title = title;
this.adapter = adapter;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//nothing to do...
}
})
.setCancelable(false)
//.setIcon(res.getDrawable(R.mipmap.ic_info_icon))
.setPositiveButton(R.string.inform_positive_button, null);
return builder.create();
}
}
public class AddPoiDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.add_poi_dialog_title)
//.setIcon(res.getDrawable(R.mipmap.ic_add_poi))
.setAdapter(new ImageListAdapter(MainActivity.this, entries, entryImgs, true), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int type = getType(which);
switch (type) {
case Types.FOUNTAIN:
addFountain();
break;
case Types.PATH:
addPathMap();
break;
case Types.HUT:
addHut();
break;
case Types.PEAK:
addPeak();
break;
case Types.BREAK_POINT:
addBreakpoint();
break;
case Types.TRASH_BIN:
addPoi(new TrashBin());
break;
case Types.PIC:
addImageMap();
break;
case Types.CELL_RECEPTION:
addCellReceptionPoi();
break;
case Types.WIFI:
addWifiPoi();
break;
case Types.LIFT:
//TODO as in path, choose two markers
addPoi(new Lift());
break;
}
}
});
return builder.create();
}
}
public void addFountain(){
AddFountainDialog addFountainDialog = new AddFountainDialog(this);
addFountainDialog.show(getFragmentManager(), "Add fountain POI Dialog");
}
public void addBreakpoint(){
AddBreakpointDialog addBreakpointDialog = new AddBreakpointDialog(this);
addBreakpointDialog.show(getFragmentManager(), "Add Break point POI Dialog");
}
public void addHut(){
AddHutDialog addHutDialog = new AddHutDialog(this);
addHutDialog.show(getFragmentManager(), "Add Hut POI Dialog");
}
public void addPeak(){
AddPeakDialog addPeakDialog = new AddPeakDialog(this);
addPeakDialog.show(getFragmentManager(), "Add Peak POI Dialog");
}
public void addPathMap() {
final MapView popupMapView = new MapView(getApplicationContext());
popupMapView.setTileSource(TileSourceFactory.MAPNIK);
popupMapView.setBuiltInZoomControls(false);
popupMapView.setMultiTouchControls(true);
IMapController popupMapController = popupMapView.getController();
popupMapController.setZoom(ZOOM_LEVEL);
popupMapController.setCenter(new GeoPoint(mLocation.getLatitude(), mLocation.getLongitude()));
List<OverlayItem> overlayItemList = new ArrayList<>();
for(Location l : foundLocations){
OverlayItem oI = new OverlayItem(String.valueOf(l.getTime()), null, null, new GeoPoint(l.getLatitude(), l.getLongitude(), l.getAltitude()));
oI.setMarker(res.getDrawable(R.mipmap.ic_poi_red));
overlayItemList.add(oI);
}
List<Poi> poiMarker = dbHandler.getAllPois();
for(Poi p : poiMarker){
DbGeoPoint dbgp = p.getGp();
GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
OverlayItem oI = new OverlayItem(String.valueOf(dbgp.getTime()), String.valueOf(p.getId()), String.valueOf(p.getType()), gp);
Drawable[] iconLayer = new Drawable[2];
iconLayer[0] = res.getDrawable(R.mipmap.ic_poi);
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(entryImgs[getPos(p.getType())]);
if(bd == null) continue;
Bitmap b = bd.getBitmap();
Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
bd = new BitmapDrawable(res, bResized);
bd.setGravity(Gravity.CENTER_HORIZONTAL);
iconLayer[1] = bd;
LayerDrawable icon = new LayerDrawable(iconLayer);
oI.setMarker(icon);
overlayItemList.add(oI);
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setView(popupMapView)
.setTitle(R.string.path_map_dialog_title)
.setPositiveButton(R.string.continue_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AddPathDialog addPathDialog = new AddPathDialog(MainActivity.this);
addPathDialog.show(getFragmentManager(), "Add Path POI Dialog");
}
})
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog pathMapDialog = builder.create();
pathMapDialog.show();
pathMapDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
final MapDialogItemizedIconOverlay overlay = new MapDialogItemizedIconOverlay(this, overlayItemList, pathMapDialog, popupMapView);
MapEventsReceiver eventsReceiver = new MapEventsReceiver() {
@Override
public boolean singleTapConfirmedHelper(GeoPoint geoPoint) {
return false;
}
@Override
public boolean longPressHelper(GeoPoint geoPoint) {
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(VIB_LENGTH);
OverlayItem oI = new OverlayItem("", null, null, geoPoint);
oI.setMarker(getApplicationContext().getResources().getDrawable(R.mipmap.ic_poi_red));
overlay.addItem(oI);
popupMapView.invalidate();
return true;
}
};
popupMapView.getOverlays().add(new MapEventsOverlay(getApplicationContext(), eventsReceiver));
popupMapView.getOverlays().add(overlay);
}
public void addImageMap() {
final MapView popupMapView = new MapView(getApplicationContext());
popupMapView.setTileSource(TileSourceFactory.MAPNIK);
popupMapView.setBuiltInZoomControls(false);
popupMapView.setMultiTouchControls(true);
IMapController popupMapController = popupMapView.getController();
popupMapController.setZoom(ZOOM_LEVEL);
popupMapController.setCenter(new GeoPoint(mLocation.getLatitude(), mLocation.getLongitude()));
List<OverlayItem> overlayItemList = new ArrayList<>();
List<Poi> poiMarker = dbHandler.getAllPois();
for(Poi p : poiMarker){
DbGeoPoint dbgp = p.getGp();
GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
OverlayItem oI = new OverlayItem(String.valueOf(dbgp.getTime()), String.valueOf(p.getId()), String.valueOf(p.getType()), gp);
Drawable[] iconLayer = new Drawable[2];
iconLayer[0] = res.getDrawable(R.mipmap.ic_poi);
BitmapDrawable bd = (BitmapDrawable) res.getDrawable(entryImgs[getPos(p.getType())]);
if(bd == null) continue;
Bitmap b = bd.getBitmap();
Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
bd = new BitmapDrawable(res, bResized);
bd.setGravity(Gravity.CENTER_HORIZONTAL);
iconLayer[1] = bd;
LayerDrawable icon = new LayerDrawable(iconLayer);
oI.setMarker(icon);
overlayItemList.add(oI);
}
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setView(popupMapView)
.setTitle(R.string.image_map_dialog_title) //TODO title
.setPositiveButton(R.string.continue_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, SELECT_POI_PHOTO);
}
})
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog pathMapDialog = builder.create();
pathMapDialog.show();
pathMapDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
final ImageDialogItemizedIconOverlay overlay = new ImageDialogItemizedIconOverlay(this, overlayItemList, pathMapDialog, popupMapView);
popupMapView.getOverlays().add(overlay);
}
private void addCellReceptionPoi(){
setActiveNetwork();
if(activeNetwork != null && activeNetwork.isConnected()){
if(tm != null && networkStrength != -1){
String opName = tm.getNetworkOperatorName();
String opCountry = tm.getNetworkCountryIso();
String nwType = activeNetwork.getSubtypeName();
int roaming = (tm.isNetworkRoaming()) ? 1 : 0;
int strength = networkStrength;
addPoi(new CellReception(0, strength, opName, opCountry, roaming, nwType, null));
} else {
Log.d(TAG, "You are not connected to a phone network");
}
} else {
Log.d(TAG, "You are not connected to any network");
}
}
private void addWifiPoi(){
if(!wm.isWifiEnabled()){
AlertDialog.Builder wifiIntentDialogBuilder = new AlertDialog.Builder(MainActivity.this);
wifiIntentDialogBuilder
.setTitle(R.string.wifi_disabled_title)
.setMessage(R.string.wifi_disabled_text)
.setPositiveButton(R.string.enable_wifi_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
startActivity(intent);
}
})
.setNegativeButton(R.string.dont_enable_wifi_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog wifiIntentDialog = wifiIntentDialogBuilder.create();
wifiIntentDialog.show();
} else {
setActiveNetwork();
if (activeNetwork != null && activeNetwork.isConnected()) {
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
String ssid = wm.getConnectionInfo().getSSID();
int rssi = wm.getConnectionInfo().getRssi();
int levels = WifiManager.calculateSignalLevel(rssi, MAX_WIFI_LEVELS);
Log.d(TAG, "You are currently connected to '" + ssid + "' with " + levels + " (" + rssi + ")");
addPoi(new Wifi(0, ssid, levels, null));
} else {
Log.d(TAG, "Wifi network not available/connected");
}
} else {
Log.d(TAG, "You are not connected to any network");
}
}
}
private void addImagePoi(Uri data){
byte[] imgData = createImage(data);
if(imgData == null || imageMarker == null) Log.d(TAG, "image data or marker is null...");
String file = getFilePath(data);
int type = Integer.parseInt(imageMarker.getSnippet()); //Long.parseLong(uidParts[1]);
DbGeoPoint dbgp = null;
ExifInterface exifInterface = null;
try {
exifInterface = new ExifInterface(file);
} catch(IOException e){
Log.e(TAG, "File " + file + " not found!");
}
float[] exifLatLon = new float[2];
if(exifInterface != null && exifInterface.getLatLong(exifLatLon)){
double alt = exifInterface.getAltitude(0);
SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy:M:d H:m:s");
String timestamp = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
long time = 0;
if(timestamp != null){
try {
time = timestampFormat.parse(timestamp).getTime() / 1000;
} catch(ParseException pe) {
pe.printStackTrace();
}
}
dbgp = new DbGeoPoint(exifLatLon[0], exifLatLon[1], alt, time);
long rowId = addGp(dbgp);
dbgp.setId(rowId);
} else {
long id = Long.parseLong(imageMarker.getTitle());
dbgp = dbHandler.getPoi(id, type).getGp();
}
addPoi(new Image(0, imgData, type, dbgp));
}
public long addGp(DbGeoPoint dbgp){
return dbHandler.addPoi(dbgp);
}
public long addPoi(Poi poi){
DbGeoPoint dbgp = poi.getGp();
if(dbgp == null){
double _lat = mLocation.getLatitude();
double _lon = mLocation.getLongitude();
double _alt = mLocation.getAltitude();
long _time = System.currentTimeMillis() / 1000;
dbgp = new DbGeoPoint(_lat, _lon, _alt, _time);
long gp_id = dbHandler.addPoi(dbgp);
dbgp.setId(gp_id);
poi.setGp(dbgp);
}
long rowId = dbHandler.addPoi(poi);
if(rowId >= 0) Toaster(getString(R.string.add_poi_success), true);
return rowId;
}
private byte[] createImage(Uri uri) {
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
} catch (FileNotFoundException e) {
Log.e(TAG, "The file at Uri " + uri.toString() + " does not exist!");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
class GetPoiFromOsm extends AsyncTask<String, Void, ArrayList> {
protected ArrayList<POI> doInBackground(String... params) {
try {
NominatimPOIProvider poiProvider = new NominatimPOIProvider("");
ArrayList<POI> foundPois = poiProvider.getPOICloseTo(new GeoPoint(mLocation), params[0], 50, 0.1);
pois.put(params[0], foundPois);
return foundPois;
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(ArrayList arrayList) {
for(POI p : (ArrayList<POI>) arrayList) {
Log.d(TAG, p.mCategory + ", " + p.mType + ", " + p.mUrl);
}
}
}
private class WarningListAdapter extends ArrayAdapter<String> {
private final Activity context;
private final String[] texts;
private final String[] descs;
public WarningListAdapter(Activity context, String[] texts, String[] descs) {
super(context, R.layout.warning_list_item, texts);
this.context = context;
this.texts = texts;
this.descs = descs;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.warning_list_item, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.warning_text_title);
TextView txtDesc = (TextView) rowView.findViewById(R.id.warning_text_desc);
txtTitle.setText(texts[position]);
txtDesc.setText(descs[position]);
return rowView;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case SELECT_POI_PHOTO:
if(resultCode == RESULT_OK){
addImagePoi(data.getData());
}
break;
}
}
@Override
public void setTitle(CharSequence title){
mTitle = title;
ActionBar actionBar = getSupportActionBar();
if(actionBar != null) actionBar.setTitle(mTitle);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, GPS_MIN_TIME, GPS_MIN_DIST, this);
}
@Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private String getFilePath(Uri uri){
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, filePathColumn, null, null, null);
String filePath = null;
if(cursor.moveToFirst()){
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
}