LocationLayout.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. package com.ivalentin.margolariak;
  2. import java.util.Locale;
  3. import com.google.android.gms.maps.CameraUpdateFactory;
  4. import com.google.android.gms.maps.GoogleMap;
  5. import com.google.android.gms.maps.MapView;
  6. import com.google.android.gms.maps.MapsInitializer;
  7. import com.google.android.gms.maps.OnMapReadyCallback;
  8. import com.google.android.gms.maps.model.BitmapDescriptorFactory;
  9. import com.google.android.gms.maps.model.LatLng;
  10. import com.google.android.gms.maps.model.Marker;
  11. import com.google.android.gms.maps.model.MarkerOptions;
  12. import android.app.Activity;
  13. import android.content.Context;
  14. import android.content.pm.PackageManager;
  15. import android.database.Cursor;
  16. import android.database.sqlite.SQLiteDatabase;
  17. import android.location.Criteria;
  18. import android.location.Location;
  19. import android.location.LocationListener;
  20. import android.location.LocationManager;
  21. import android.os.Bundle;
  22. import android.app.Fragment;
  23. import android.os.Handler;
  24. import android.support.v4.app.ActivityCompat;
  25. import android.util.Log;
  26. import android.view.LayoutInflater;
  27. import android.view.View;
  28. import android.view.ViewGroup;
  29. import android.widget.TextView;
  30. /**
  31. * Section that shows a map with the location of Gasteizko Margolariak.
  32. * If no recent report location, it will explain that and will show the
  33. * next scheduled activity.
  34. *
  35. * @author Iñigo Valentin
  36. *
  37. * @see Fragment
  38. * @see OnMapReadyCallback
  39. *
  40. */
  41. public class LocationLayout extends Fragment implements OnMapReadyCallback, LocationListener {
  42. //The map view
  43. private MapView mapView;
  44. GoogleMap gMap;
  45. private LocationManager locationManager;
  46. //Locations for the user and Gasteizko Margolariak
  47. private LatLng gmLocation;
  48. //The main View
  49. private View v;
  50. private double lat, lon;
  51. //Map marker
  52. Marker gmMarker;
  53. MarkerOptions moGm = new MarkerOptions();
  54. private final Handler markerHandler = new Handler();
  55. private final Runnable resetMarker = new Runnable() {
  56. @Override
  57. public void run() {
  58. if (gmMarker != null) {
  59. gmMarker.remove();
  60. if (refreshLocation()) {
  61. gmMarker.setPosition(new LatLng(lat, lon));
  62. gmLocation = new LatLng(lat, lon);
  63. //moGm = new MarkerOptions();
  64. moGm.title(v.getContext().getString(R.string.app_name));
  65. moGm.position(gmLocation);
  66. moGm.icon(BitmapDescriptorFactory.fromResource(R.drawable.pinpoint_gm));
  67. gmMarker = gMap.addMarker(moGm);
  68. }
  69. }
  70. markerHandler.postDelayed(resetMarker, GM.LOCATION.INTERVAL);
  71. }
  72. };
  73. /**
  74. * Run when the fragment is inflated.
  75. *
  76. * @param inflater A LayoutInflater to manage views
  77. * @param container The container View
  78. * @param savedInstanceState Bundle containing the state
  79. *
  80. * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
  81. */
  82. @Override
  83. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
  84. //Get the view
  85. v = inflater.inflate(R.layout.fragment_layout_location, container, false);
  86. //Set up
  87. locationManager = (LocationManager) v.getContext().getSystemService(Context.LOCATION_SERVICE);
  88. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)){
  89. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GM.LOCATION.ACCURACY.TIME, GM.LOCATION.ACCURACY.SPACE, this);
  90. }
  91. //Set the title
  92. ((MainActivity) getActivity()).setSectionTitle(v.getContext().getString(R.string.menu_location));
  93. //Refresh the location.
  94. refreshLocation();
  95. //Periodically check map
  96. markerHandler.post(resetMarker);
  97. mapView = (MapView) v.findViewById(R.id.mapview);
  98. mapView.onCreate(savedInstanceState);
  99. // Gets to GoogleMap from the MapView and does initialization stuff
  100. mapView.getMapAsync(this);
  101. //Return the view
  102. return v;
  103. }
  104. /**
  105. * Called when the fragment is bought back to the foreground.
  106. * Ensures that the map is displayed then, and activates the location manager.
  107. *
  108. * @see android.app.Fragment#onResume()
  109. */
  110. @Override
  111. public void onResume() {
  112. if (mapView != null) {
  113. mapView.onResume();
  114. }
  115. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)){
  116. locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GM.LOCATION.ACCURACY.TIME, GM.LOCATION.ACCURACY.SPACE, this);
  117. }
  118. super.onResume();
  119. markerHandler.post(resetMarker);
  120. }
  121. /**
  122. * Called when the fragment is paused.
  123. * Stops the location manager
  124. * @see android.app.Fragment#onPause()
  125. */
  126. @Override
  127. public void onPause(){
  128. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
  129. locationManager.removeUpdates(this);
  130. }
  131. super.onPause();
  132. markerHandler.removeCallbacks(resetMarker);
  133. }
  134. /**
  135. * Called when the fragment is destroyed.
  136. * Ensures that the map is destroyed then.
  137. *
  138. * @see android.support.v4.app.Fragment#onDestroy()
  139. */
  140. @Override
  141. public void onDestroy() {
  142. super.onDestroy();
  143. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
  144. locationManager.removeUpdates(this);
  145. }
  146. if (mapView != null){
  147. mapView.onResume();
  148. mapView.onDestroy();
  149. }
  150. markerHandler.removeCallbacks(resetMarker);
  151. }
  152. /**
  153. * Called in a situation of low memory.
  154. * It let's the mapView handle the situation.
  155. *
  156. * @see android.support.v4.app.Fragment#onLowMemory()
  157. */
  158. @Override
  159. public void onLowMemory() {
  160. super.onLowMemory();
  161. if (mapView != null){
  162. mapView.onResume();
  163. mapView.onLowMemory();
  164. }
  165. }
  166. /**
  167. * Refresh the global variables "lat" and "lon".
  168. *
  169. * Uses the most recent data in the database, if they are not older than 10 minutes.
  170. *
  171. * @return true if there is a location from less than 10 minutes ago, 0 otherwise.
  172. */
  173. private boolean refreshLocation(){
  174. SQLiteDatabase db = getActivity().openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
  175. Cursor cursor;
  176. cursor = db.rawQuery("SELECT lat, lon FROM location WHERE dtime >= Datetime('now', '-10 minutes') ORDER BY dtime DESC LIMIT 1;", null);
  177. if (cursor.getCount() == 0){
  178. cursor.close();
  179. db.close();
  180. return false;
  181. }
  182. else {
  183. cursor.moveToFirst();
  184. lat = cursor.getDouble(0);
  185. lon = cursor.getDouble(1);
  186. cursor.close();
  187. db.close();
  188. return true;
  189. }
  190. }
  191. /**
  192. * Called when the map is ready to be used.
  193. * Initializes it and sets the Gasteizko Margolariak marker.
  194. *
  195. * @param googleMap the map
  196. *
  197. * @see com.google.android.gms.maps.OnMapReadyCallback#onMapReady(com.google.android.gms.maps.GoogleMap)
  198. */
  199. @Override
  200. public void onMapReady(GoogleMap googleMap) {
  201. gMap = googleMap;
  202. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
  203. googleMap.setMyLocationEnabled(true);
  204. }
  205. googleMap.getUiSettings().setMyLocationButtonEnabled(false);
  206. // Needs to call MapsInitializer before doing any CameraUpdateFactory calls
  207. try {
  208. MapsInitializer.initialize(this.getActivity());
  209. } catch (Exception e) {
  210. Log.e("Error initializing maps", e.toString());
  211. }
  212. //If there is a location, set it
  213. if (refreshLocation()) {
  214. //Set the marker
  215. gmLocation = new LatLng(lat, lon);
  216. moGm.title(v.getContext().getString(R.string.app_name));
  217. moGm.position(gmLocation);
  218. moGm.icon(BitmapDescriptorFactory.fromResource(R.drawable.pinpoint_gm));
  219. gmMarker = googleMap.addMarker(moGm);
  220. googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), 14.0f));
  221. }
  222. //Start device location requests
  223. if (!(ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
  224. locationManager.requestLocationUpdates(locationManager.getBestProvider(new Criteria(), true), GM.LOCATION.ACCURACY.TIME, GM.LOCATION.ACCURACY.SPACE, this);
  225. onLocationChanged(locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER));
  226. }
  227. }
  228. private void calCulateDistance(Location userLocation){
  229. TextView text = (TextView) v.findViewById(R.id.tv_location_distance);
  230. try {
  231. Double distance = Distance.calculateDistance(userLocation.getLatitude(), userLocation.getLongitude(), lat, lon);
  232. if (distance <= 2) {
  233. distance = 1000 * distance;
  234. text.setText(String.format(getString(R.string.home_section_location_text_short), distance.intValue(), (int) (0.012 * distance.intValue())));
  235. } else {
  236. text.setText(String.format(getString(R.string.home_section_location_text_long), String.format(Locale.US, "%.02f", distance)));
  237. }
  238. }
  239. catch(Exception ex){
  240. Log.e("Distance error", ex.toString());
  241. text.setText("");
  242. }
  243. }
  244. /**
  245. * Called when the user location changes.
  246. * Recalculates the list of around events and calls updateLocation() to
  247. * update the distance in the location section.
  248. *
  249. * @param location The new location
  250. *
  251. * @see android.location.LocationListener#onLocationChanged(android.location.Location)
  252. */
  253. @Override
  254. public void onLocationChanged(Location location) {
  255. calCulateDistance(location);
  256. }
  257. /**
  258. * Called when the location provider changes it's state.
  259. *
  260. * @param provider The name of the provider
  261. * @param status Status code of the provider
  262. * @param extras Extras passed
  263. *
  264. * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
  265. */
  266. @Override
  267. public void onStatusChanged(String provider, int status, Bundle extras) {
  268. //populateAround();
  269. }
  270. /**
  271. * Called when a location provider is enabled.
  272. * Recalculates the list of events.
  273. *
  274. * @param provider The name of the provider
  275. *
  276. * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
  277. */
  278. @Override
  279. public void onProviderEnabled(String provider) {
  280. //populateAround();
  281. }
  282. /**
  283. * Called when a location provider is disabled.
  284. * Recalculates the list of events.
  285. *
  286. * @param provider The name of the provider
  287. *
  288. * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
  289. */
  290. @Override
  291. public void onProviderDisabled(String provider) {
  292. //populateAround();
  293. }
  294. }