SMB - Geolokalizacja Michail Mokkas
Czym jest geolokalizacja? „Położenie oraz proces określenia geograficznego położenia objektów fizycznych” Położenie określane jest poprzez współrzędne geograficzne: długość oraz szerokość geograficzną
GPS Global Positioning System (NAVSTAR) System nawigacyjny składający się z 31 (24 aktywne) satelit orbitujących wokół ziemi a także infrastruktury naziemnej kontrolującej/monitorującej je oraz odbiorników sygnału (użytkowników).
Sieć Komórkowa Znalezienie się w zasięgu stacji bazowych (BTS)
Inne metody Po IP Rozpoznawanie krajobrazu (zdjęcia – punkty orientacyjne) Użytkownik sam wpisuje ;)
Android Location API Google Play services location API (preferowany) Potrzebny jest Google Play services SDK Wymagania oraz instalacja na stronie Należy także dopisać bibliotekę do naszego projektu:
Ostatnia znana lokalizacja Aplikacja nie może uaktualnić na żądanie współrzędnych (pobrać nowe bezpośrednio od modułu GPS) W celu ich uzyskania musi korzystać z providera „LocationProvider” lub wyłapać zmianę lokalizacji za pomocą LocationListenera Można wybrać metodę użytą do obliczenia współrzędnych: Network - korzysta z sieci komórkowej lub Wi-Fi, do której podpięte jest urządzenie (dostawca usług musi wspierać taką możliwość) GPS – korzysta z odbiornika GPS urządzenia (wymaga 7 satelit) Passive – pozwala na uzyskanie współrzędnych w sposób najmniej obciążający pobór energii (czekamy aż inna aplikacja poprosi o współrzędne)
LocationManager LocationManager – umożliwia korzystanie z usług lokalizacyjnych . Criteria – klasa reprezentująca kryteria lokalizacyjne (np. precyzja, pobór energii, szybkość, możliwość podania wysokości) getBestProvider(Criteria, boolean) – zwraca nazwę dostawcy, który najlepiej pasuje do kryteriów. Drugi argument to stan dostawcy (aktywny lub nie). getLastKnownLocation(String) – zwraca ostatnią znaną lokalizację danego dostawcy (provider). Może być nieaktualna lub nawet null jeżeli dostawca jest aktualnie nieaktywny.
LocationManager kont. 1 Uzyskanie obiektu LocationManager wraz z wyznaczeniem providera
LocationManager kont.2 Wyświetlenie uzyskanych współrzędnych: Powinniśmy też dodać permissions w AndroidManifest.xml: INTERNET ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION android.hardware.location.network (dla API 21+) android.hardware.location.gps (dla API 21+)
LocationListener LocationListener - nasłuchuje na zmiany związane z położeniem. Poniższe metody są wywoływane po zarejestrowaniu LocationListenera (metoda requestLocationUpdates() na location manager). Podczas wywołania requestLocationUpdates() apka nasłuchuje na zmiany w lokalizacji. onLocationChanged(Location) – wywołana, kiedy następuje zmiana położenia. onStatusChanged(String, int, b) – wywołana, kiedy stan dostawcy jest zmieniony. onProviderDisabled(String) – wywołana, kiedy dostawca jest dezaktywowany przez użytkownika. onProviderEnabled(String) – wywołana, kiedy dostawca jest aktywowany przez użytkownika. Od API 26+, jeżeli nasz apka chodzi w tle i prosi o lokalizację, to jest to szacowane jedynie kilka razy na godzinę.
LocationListener - przykład int minCzas = 0; int minDystans = 0; LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); LocationListener ll = new LocationListener() { public void onLocationChanged(Location location) { zmienLokalizacje(location); } public void onStatusChanged(String provider, int status, Bundle extras) { } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { } }; if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minCzas, minDystans, ll); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, minCzas, minDystans, ll);
Location Updates Warto pamiętać, by w momencie, kiedy nie potrzebujemy już nowych współrzędnych, zakończyć nasłuchiwanie: Nasłuchiwanie na zmiany związane z geolokalizacją są niestety zasobożerne i mogą szybko wyczerpać baterię urządzenia. lm.removeUpdates(ll);
Proximity Alert Istnieje także możliwość wyznaczenia obszaru (lat, long, radius). Za pomocą metody addProximityAlert() i przypisaniu do niej intencji, uzyskujemy zdarzenie, które się wywoływuje po wejściu na wyznaczony teren. Przypisana intencja może być wyłapana przez nasz BroadcastReceiver, który z kolei może dalej decydować, co zrobić z tą informacją. Alternatywnie, można w tym celu wykrozystać też Geofence.
Google Play Location Service API Rekomendowany sposób do zarządzania i wykorzystania geolokalizacji w aplikacjach. Jest wyższego poziomu względem android.location . Zwykle oferuje niższe zużycie zasobów (w tym baterii). Wykorzystuje FusedLocationClient do działań związanych z geolokalizacją.
Location Provider Client Ostatnia lokalizacja poprzez FusedLocationProviderClient:
Geofence - ustanowienie monitorowania private GeofencingClient gc; @Override public void onCreate(Bundle savedInstanceState) { gc = LocationServices.getGeofencingClient(this); }
Geofence - dodanie obiektu MyPlace place; long expiration = 3600000L; geoList.add(new Geofence.Builder() .setRequestId(place.getKey()) .setCircularRegion( place.getLatitude(), place.getLongtitude(), place.getRadius() ).setExpirationDuration(expiration) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build());
Geofence - wyzwalacze Następnie należy wyspecyfikować wyzwalacze (triggers), czyli, na jakie zjawiska/zmiany powininen nasz Geofence reagować. Możliwe wyzwalacze: GEOFENCE_TRANSITION_ENTER GEOFENCE_TRANSITION_EXIT INITIAL_TRIGGER_ENTER (powoduje, że ENTER się wyzwoli nawet, kiedy początkowo znajdujemy się w polu) INITIAL_TRIGGER_DWELL (pozwala złagodzić spam, działa kiedy użytkownik zatrzyma się na określony czas)
Geofence - nasłuchiwanie public class MyGeofenceTransitionsIntentService extends IntentService { protected void onHandleIntent(Intent intent) { GeofencingEvent ge = GeofencingEvent.fromIntent(intent); int gt = ge.getGeofenceTransition(); if (gt == Geofence.GEOFENCE_TRANSITION_ENTER || gt == Geofence.GEOFENCE_TRANSITION_EXIT) { List<Geofence> tg = ge.getTriggeringGeofences(); String gtd = getGeofenceTransitionDetails(this, gt, tg); Toast.makeText(getApplicationContext(), gtd, Toast.LENGTH_SHORT); } else { Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT); } } }
Prośba o włączenie odbiornika GPS Powinniśmy poinformować użytkownika o uruchomieniu odbiornika GPS w celu uzyskania współrzędnych:
Geocoder Umożliwia zamianę obiektu lokalizacji (geograficznych współrzędnych) na adres (nazwę ulicy, numer domu/obiektu). Działa też w drugą stronę. Korzysta z usługi online Zapisuje kilka adresów, które znajdują się w pobliżu lokalizacji getFromLocation(double,double,int) - szuka na podstawie współrzędnych i zwraca kilka wyników (ich ilość to 3 argument).
Lokalizacja na emulatorze Istnieje możliwość ustawienia współrzędnych na emulatorze aby upozorować położenie
Google Maps Android API v2 Biblioteka umożliwiająca wyświetlanie map i dodawania na nich elementów takich jak: Markers Polylines Polygons Ground Overlays Tile Overlays
Marker Jest to ikonka wskazująca na jakiś punkt (pozycję) na mapie. set/getPosition(LatLng) – ustawia/zwraca współrzędne geograficzne markera. set/getTitle(String) – ustala/zwraca tytuł markera. setIcon() – ustala ikonkę reprezentującą marker. setDraggable() –ustala czy marker może być poruszany przez użytkownika. remove() – usuwa marker z mapy.
Polyline Jest to linia wyznaczona przez podane punkty na mapie. set/getPoints() – ustala/zwraca punkty wyznaczające linię. set/getWidth() – ustawia/zwraca szerokość linii (w pikselach, domyślnie 10). set/getColor() – ustawia/zwraca kolor linii. remove() – usuwa linię. setZIndex() – ustala „poziom” linii (linie z wyższym indeksem Z są rysowane nad tymi z niższym w przypadku kiedy na siebie nachodzą)
Polygon Jest to kształt (wielokąt), który zaznacza część mapy. Może posiadać dziury (miejsca w środku wielokątu, które nie obejmuje). set/getPoints() – ustawia/zwraca punkty, które wyznaczają wielokąt. set/getStrokeWidth() – ustawia/ zwraca szerokość linii (granicy). set/getStrokeColor() – ustawia/zwraca kolor linii. set/getFillColor() – ustawia/zwraca kolor wypełnienia. remove() – usuwa wielokąt.
Circle Jest to kształt (koło) wyznaczany na mapie. set/getCenter() – ustala/zwraca punkt środkowy koła. set/getFillColor() – ustawia/zwraca kolor wypełnienia koła. set/getRadius() – ustala/zwraca długość promienia koła. set/getStrokeWidth() – ustawia/zwraca szerokość okręgu. set/getStrokeColor() – ustawia/zwraca kolor okręgu. remove() – usuwa koło.
Ground/Tile Overlay Stanowi rysunek (lub grupę rysunków) utwierdzony na mapie. set/getPosition() – ustala/zwraca pozycję umiejscowienia rysunku. setImage() – ustawia rysunek. setgetBearing() – ustawia/zwraca rotację. (zgodnie ze wskazówkami zegara od północy) set/getTransparency() – ustala/zwraca poziom przezroczystości (0 – rysunek nie widoczny, 1 – mapa pod rysunkiem nie widoczna). remove() – usuwa rysunek.
Korzystanie Aby skorzystać z biblioteki, powinniśmy dodać do AndroidManifest.xml następujące elementy: W tagu <application> jako ostatni element:
Otrzymanie klucza Google Map Aby korzystać z Google Maps API, musimy posiadać specjalny do tego celu klucz (Google Maps API key). Klucz można uzyskać za pośrednictwem Google APIs Console. Scieżka do debug key: /users/USER/.android/debug.keystore Należy wykonać następujące polecenie:
Otrzymanie klucza kont. 1 Należy zapisać uzyskany w ten sposób skrót (SHA-1) Następnie rejestrujemy się na Google APIs Console W tabie Services aktywujemy Google Maps Android API v2 W tabie API Access rejestrujemy naszą aplikację Klikamy na „Create new Android key” I wpisujemy nasz skrót SHA-1 oraz pakiet, do którego należy nasza aplikacja
Otrzymanie klucza kont. 2 <resources> <!-- TODO: Before you run your application, you need a Google Maps API key. To get one, follow this link, follow the directions and press "Create" at the end: https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r= <tutaj hash> You can also add your credentials to an existing key, using these values: Package name: <tutaj hash> SHA-1 certificate fingerprint: <tutaj hash> Alternatively, follow the directions here: https://developers.google.com/maps/documentation/android/start#get-key Once you have your key (it starts with "AIza"), replace the "google_maps_key" string in this file. --> <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string> </resources>
MapFragment Layout.xml do fragmentu reprezentującego mapę:
Mapa w kodzie GoogleMap – podstawowa klasa Google Maps Android API. Otrzymujemy poprzez metodę getMap() aktywności lub fragmentu mapy (MapView, MapFragment). addMarker(MarkerOptions) – dodaje marker do mapy. addPolygon(PolygonOptions) – dodaje wielokąt do mapy. addPolyline(PolylineOptions) – dodaje linię do mapy. addTileOverlay(TileOverlayOptions) – dodaje rysunek do mapy.
Mapa w kodzie kont. 1 animateCamera(CameraUpdate, int) – porusza mapę zgodnie z wybranym sposobem oraz czasem trwania (opcjonalnie wywołuje callback jak skończy). stopAnimation() – zatrzymuje animację kamery (pozostaje w miejscu zatrzymania ruchu). moveCamera(CameraUpdate) – repozycjonuje kamerę zgodnie z instrukcjami podanymi jako argument. setTrafficEnabled(boolean) – ustawia widoczność warstwy ruchu ulicznego. snapshot() – tworzy zrzut mapy.
Mapa w kodzie (listenery) kont. 2 Możemy wyznaczyć nasłuchiwanie na: OnCameraChangeListener – wyłapuje zmiany pozycji kamery. W trakcie animacji wyłapuje jedynie ostateczną pozycję. OnInfoWindowClickListener – wyłapuje dotknięcie przez użytkownika dymku z opisem markera. OnMapClickListener – wyłapuje dotknięcie przez użytkownika na mapę (jedynie w przypadku kiedy użytkownik nie dotkną elementu, na którym także prowadzone jest nasłuchiwanie na gesty). OnMapLoadedCallback- wyłapuje koniec rysowania mapy.
Mapa w kodzie (listenery) kont. 3 OnMapLongClickListener – wyłapuje gest dłuższego przytrzymania przez użytkownika na mapie. Jedynie jeżeli nie jest już obsługiwany przez inny element map. OnMarkerClickListener – wyłapuje dotknięcie przez uzytkownika markera na mapie. OnMarkerDragListener – wyłapuje przesuwanie przez użytkownika markera na mapie. OnMyLocationButtonClickListener – wyłapuje dotknięcie przez użytkownika guzika „moja lokalizacja” na mapie
Mapa w kodzie kont. 1 setMapType() – ustawia typ pokazywanej mapy: MAP_TYPE_NORMAL MAP_TYPE_HYBRID MAP_TYPE_TERRAIN
Mapa z markerem public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mapa; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } @Override public void onMapReady(GoogleMap googleMap) { mapa = googleMap; LatLng sydney = new LatLng(-34, 151); MarkerOptions mo = new MarkerOptions(); mo.position(sydney); mo.title("Sydney"); mo.snippet("The most populous city in Australia."); mapa.addMarker(mo); mapa.moveCamera(CameraUpdateFactory.newLatLng(sydney)); } } https://developers.google.com/maps/documentation/android/
Rezultat https://developers.google.com/maps/documentation/android/