LocationLayout.java 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package com.ivalentin.margolariak;
  2. import java.util.Locale;
  3. import java.util.ArrayList;
  4. import android.app.Activity;
  5. import android.content.Context;
  6. import android.content.pm.PackageManager;
  7. import android.database.Cursor;
  8. import android.database.sqlite.SQLiteDatabase;
  9. import android.location.Location;
  10. import android.location.LocationListener;
  11. import android.location.LocationManager;
  12. import android.os.Bundle;
  13. import android.app.Fragment;
  14. import android.os.Handler;
  15. import android.util.Log;
  16. import android.view.LayoutInflater;
  17. import android.view.View;
  18. import android.view.ViewGroup;
  19. import android.widget.TextView;
  20. import android.graphics.drawable.Drawable;
  21. import org.osmdroid.api.IMapController;
  22. import org.osmdroid.util.GeoPoint;
  23. import org.osmdroid.views.MapView;
  24. import org.osmdroid.views.overlay.ItemizedIconOverlay;
  25. import org.osmdroid.views.overlay.OverlayItem;
  26. /**
  27. * Section that shows a map with the location of Gasteizko Margolariak.
  28. *
  29. * @author Iñigo Valentin
  30. *
  31. * @see Fragment
  32. *
  33. */
  34. public class LocationLayout extends Fragment implements LocationListener {
  35. //The map view stuff
  36. private MapView mapView;
  37. private Drawable locationMarker;
  38. // The location manager
  39. private LocationManager locationManager;
  40. //Locations for the user and Gasteizko Margolariak
  41. private GeoPoint gmLocation;
  42. //The main View
  43. private View v;
  44. // Handler to refresh the location.
  45. private final Handler markerHandler = new Handler();
  46. private final Runnable resetMarker = new Runnable() {
  47. @Override
  48. public void run() {
  49. if (mapView != null) {
  50. if (refreshLocation()) {
  51. //mapController.setCenter(self.gmLocation);
  52. OverlayItem locationOverlayItem = new OverlayItem("Gasteizko Margolariak", "", gmLocation);
  53. locationOverlayItem.setMarker(locationMarker);
  54. final ArrayList<OverlayItem> items = new ArrayList<>();
  55. items.add(locationOverlayItem);
  56. ItemizedIconOverlay locationOverlay = new ItemizedIconOverlay<>(items,
  57. new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
  58. public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
  59. return true;
  60. }
  61. public boolean onItemLongPress(final int index, final OverlayItem item) {
  62. return true;
  63. }
  64. }, getContext());
  65. mapView.getOverlays().add(locationOverlay);
  66. }
  67. }
  68. markerHandler.postDelayed(resetMarker, GM.LOCATION.INTERVAL);
  69. }
  70. };
  71. /**
  72. * Run when the fragment is inflated.
  73. *
  74. * @param inflater A LayoutInflater to manage views
  75. * @param container The container View
  76. * @param savedInstanceState Bundle containing the state
  77. *
  78. * @see Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
  79. */
  80. @Override
  81. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
  82. //Get the view
  83. v = inflater.inflate(R.layout.fragment_layout_location, container, false);
  84. //Set up
  85. locationManager = (LocationManager) v.getContext().getSystemService(Context.LOCATION_SERVICE);
  86. if (checkLocationPermission()){
  87. locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, this, null);
  88. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GM.LOCATION.ACCURACY.TIME, GM.LOCATION.ACCURACY.SPACE, this);
  89. }
  90. //Set the title
  91. ((MainActivity) getActivity()).setSectionTitle(v.getContext().getString(R.string.menu_location));
  92. //Refresh the location.
  93. refreshLocation();
  94. //Periodically check map
  95. markerHandler.post(resetMarker);
  96. // Set up the map
  97. this.mapView = (MapView) v.findViewById(R.id.mapview);
  98. this.mapView.setMultiTouchControls(true);
  99. IMapController mapController = mapView.getController();
  100. mapController.setZoom(17);
  101. mapController.setCenter(gmLocation);
  102. this.locationMarker = this.getResources().getDrawable(R.drawable.pinpoint, null);
  103. //Return the view
  104. return v;
  105. }
  106. /**
  107. * Called when the fragment is bought back to the foreground.
  108. * Ensures that the map is displayed then, and activates the location manager.
  109. *
  110. * @see android.app.Fragment#onResume()
  111. */
  112. @Override
  113. public void onResume() {
  114. if (checkLocationPermission()){
  115. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GM.LOCATION.ACCURACY.TIME, GM.LOCATION.ACCURACY.SPACE, this);
  116. }
  117. super.onResume();
  118. markerHandler.post(resetMarker);
  119. }
  120. /**
  121. * Called when the fragment is paused.
  122. * Stops the location manager
  123. * @see android.app.Fragment#onPause()
  124. */
  125. @Override
  126. public void onPause(){
  127. if (checkLocationPermission()) {
  128. locationManager.removeUpdates(this);
  129. }
  130. super.onPause();
  131. markerHandler.removeCallbacks(resetMarker);
  132. }
  133. /**
  134. * Called when the fragment is destroyed.
  135. * Ensures that the map is destroyed then.
  136. *
  137. * @see Fragment#onDestroy()
  138. */
  139. @Override
  140. public void onDestroy() {
  141. super.onDestroy();
  142. if (checkLocationPermission()) {
  143. locationManager.removeUpdates(this);
  144. }
  145. markerHandler.removeCallbacks(resetMarker);
  146. }
  147. /**
  148. * Refresh the location of Gasteizko Margolariak, by updating the class attribute gmLocation.
  149. *
  150. * Uses the most recent data in the database, if they are not older than 10 minutes.
  151. *
  152. * @return true if there is a location from less than 10 minutes ago, 0 otherwise.
  153. */
  154. private boolean refreshLocation(){
  155. SQLiteDatabase db = getActivity().openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
  156. Cursor cursor;
  157. cursor = db.rawQuery("SELECT lat, lon FROM location WHERE dtime >= Datetime('now', '-10 minutes') ORDER BY dtime DESC LIMIT 1;", null);
  158. if (cursor.getCount() == 0){
  159. cursor.close();
  160. db.close();
  161. return false;
  162. }
  163. else {
  164. cursor.moveToFirst();
  165. gmLocation = new GeoPoint(cursor.getDouble(0), cursor.getDouble(1));
  166. cursor.close();
  167. db.close();
  168. return true;
  169. }
  170. }
  171. /**
  172. * Recalculates the distance between the user and Gasteizko Margolariak.
  173. * Prints the distance to a TextView.
  174. *
  175. * @param userLocation The new user location.
  176. *
  177. * @see android.location.LocationListener#onLocationChanged(android.location.Location)
  178. */
  179. private void calculateDistance(Location userLocation){
  180. TextView text = (TextView) v.findViewById(R.id.tv_location_distance);
  181. if (userLocation != null){
  182. try {
  183. Double distance = Distance.calculateDistance(userLocation.getLatitude(), userLocation.getLongitude(), gmLocation.getLatitude(), gmLocation.getLongitude());
  184. if (distance <= 2) {
  185. distance = 1000 * distance;
  186. text.setText(String.format(getString(R.string.home_section_location_text_short), distance.intValue(), (int) (0.012 * distance.intValue())));
  187. } else {
  188. text.setText(String.format(getString(R.string.home_section_location_text_long), String.format(Locale.US, "%.02f", distance)));
  189. }
  190. }
  191. catch(Exception ex){
  192. Log.e("LOCATION_LAYOUT", "Distance error: " + ex.toString());
  193. text.setText("");
  194. }
  195. }
  196. }
  197. /**
  198. * Called when the user location changes.
  199. * Recalculates the list of around events and calls updateLocation() to
  200. * update the distance in the location section.
  201. *
  202. * @param location The new location
  203. *
  204. * @see android.location.LocationListener#onLocationChanged(android.location.Location)
  205. */
  206. @Override
  207. public void onLocationChanged(Location location) {
  208. calculateDistance(location);
  209. }
  210. /**
  211. * Checks app permission to access the user location.
  212. * @return true if the permission has been granted, false otherwise.
  213. *
  214. * @see android.app.Fragment#onResume()
  215. */
  216. private boolean checkLocationPermission(){
  217. return getContext().checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && getContext().checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
  218. }
  219. /**
  220. * Called when the location provider changes it's state.
  221. * Does nothing.
  222. *
  223. * @param provider The name of the provider
  224. * @param status Status code of the provider
  225. * @param extras Extras passed
  226. *
  227. * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
  228. */
  229. @Override
  230. public void onStatusChanged(String provider, int status, Bundle extras) {
  231. }
  232. /**
  233. * Called when a location provider is enabled.
  234. * Does nothing.
  235. *
  236. * @param provider The name of the provider
  237. *
  238. * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
  239. */
  240. @Override
  241. public void onProviderEnabled(String provider) {
  242. }
  243. /**
  244. * Called when a location provider is disabled.
  245. * Does nothing.
  246. *
  247. * @param provider The name of the provider
  248. *
  249. * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
  250. */
  251. @Override
  252. public void onProviderDisabled(String provider) {
  253. }
  254. }