1 komentarz

Geolokalizacja – wstęp, dostawcy danych, ostatnia znana pozycja

Sierpień 10, 2011 Geolokalizacja Tutoriale

Geolokalizacja w systemie Android zrealizowana jest na dwa sposoby. Mniej dokładny – lokalizacja określana jest na podstawie zasięgu sieci komórkowej (lub Wi-Fi), oraz bardziej dokładny – na podstawie modułu GPS. W dzisiejszym artykule zaznajomimy się z podstawami wykorzystania obu z nich.

Przykładowa aplikacja

Zadaniem aplikacji będzie pobranie i wyświetlenie ostatnio ustalonej pozycji, zarówno z modułu GPS jak i sieci (GSM/Wi-Fi). Rozwiązanie jakie dziś przedstawię powinno posłużyć jedynie jako wstęp do geolokalizacji w Androidzie. Posiada ono bowiem ogromną wadę – wyświetla naprawdę ostatnio ustaloną pozycję. W związku z tym jeżeli moduł GPS był włączony i wykorzystywany kilka godzin wcześniej (i kilkadziesiąt kilometrów dalej) – aplikacja wskaże właśnie tamtą pozycję.
W skrócie dzisiejszy przykład potrafi wyświetlić dane, ale nie potrafi ich odświeżyć (dotyczy to modułu GPS, ponieważ GSM/Wi-Fi odświeża swoje dane automatycznie).

Przygotowania

Aby móc korzystać z ustalania pozycji geograficznej w Androidzie wymagane są dwa pozwolenia:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Pierwsze daje nam dostęp do niedokładnych danych lokalizacyjnych (określanych na podstawie sieci komórkowej/WIFI). Drugie to już dokładna pozycja, określana na podstawie odbiornika GPS. Oba definiujemy w pliku AndroidManifest.xml.

Oto layout naszej aplikacji:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="20sp"
        android:text="Location Providers" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="---"
        android:id="@+id/tvLocationProviders" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Your coordinates"
        android:textSize="20sp"
        android:layout_gravity="center" />
    <TextView
        android:id="@+id/tvLatitude"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Latitude: " />
    <TextView
        android:id="@+id/tvLongitude"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Longitude: " />
</LinearLayout>

A to kod źródłowy głównej Aktywności, wraz z zaznaczonymi metodami, któe wymagają naszej implementacji:

public class MainActivity extends Activity {
	private TextView tvLatitude;
	private TextView tvLongitude;
	private TextView tvLocationProviders;

	private LocationManager locationManager;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		tvLatitude = (TextView) findViewById(R.id.tvLatitude);
		tvLongitude = (TextView) findViewById(R.id.tvLongitude);
		tvLocationProviders = (TextView) findViewById(R.id.tvLocationProviders);
		getLocationManager();
		showLocationProvidersInfo();
		showLocation();
	}
}

Usługa lokalizacji

Zaczniemy od implementacji pierwszej metody – getLocationManager(). Nie jest to nic skomplikowanego, ponieważ menedżer lokalizacji jest zwykłą usługą systemową, wobec czego dostęp do niej to tak naprawdę jedna linijka kodu. :)

public class MainActivity extends Activity {
	private TextView tvLatitude;
	private TextView tvLongitude;
	private TextView tvLocationProviders;

	private LocationManager locationManager;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		tvLatitude = (TextView) findViewById(R.id.tvLatitude);
		tvLongitude = (TextView) findViewById(R.id.tvLongitude);
		tvLocationProviders = (TextView) findViewById(R.id.tvLocationProviders);
		getLocationManager();
		showLocationProvidersInfo();
		showLocation();
	}

	private void getLocationManager() {
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
	}
}

Lista dostępnych źródeł danych

Kiedy mamy już dostęp do usługi lokalizacyjnej, możemy pobrać z niej listę dostępnych źródeł danych. Odbywa się to za pomocą metod:

  • getAllProviders() – zwraca listę wszystkich dostępnych dostawców danych lokalizacyjnych (również tych, do których nasza aplikacja może nie mieć dostępu ze względu na uprawnienia).
  • getProviders(boolean enabledOnly) – zwraca listę wszystkich dostępnych dostawców (ale tylko tych, na które mamy pozwolenie). Dodatkowo, gdy argument metody jest ustawiony na true zwrócone zostaną tylko źródła, które są aktualnie włączone.
  • getProviders(Criteria criteria, boolean enabledOnly) – zwraca listę źródeł pasujących do zadanych kryteriów.

W każdym przypadku zwrócona zostanie lista nazw źródeł w postaci napisu String.

	private void showLocationProvidersInfo() {
		String providers = getLocationProvidersInfo();
		tvLocationProviders.setText(providers);
	}

	private String getLocationProvidersInfo() {
		StringBuilder locationProviders = new StringBuilder();
		for (String providerName : locationManager.getAllProviders()) {
			locationProviders.append(providerName);
			locationProviders.append(" ");
			if (locationManager.isProviderEnabled(providerName))
				locationProviders.append("(enabled)");
			else
				locationProviders.append("(disable)");
			locationProviders.append("\n");
		}
		return locationProviders.toString();
	}

Na podstawie zwróconej nazwy możemy m.in. sprawdzić czy dostawca danych jest włączony.

Pobieranie ostatniej znanej lokalizacji

Aby pobrać dane o ostatniej znanej lokalizacji wystarczy skorzystać z metody getLastKnownLocation(String), której argumentem jest nazwa dostawcy (możemy skorzystać zarówno ze zwróconych powyżej nazw jak i stałych LocationManager.GPS_PROVIDER, LocationManager.PASSIVE_PROVIDER, LocationManager.NETWORK_PROVIDER).

Zwrócony zostanie obiekt Location, który posiada szereg danych lokalizacyjnych (m.in. dłogość/szerokość geograficzną, dokładność pomiarów, szybkość poruszania itp.). W przypadku gdy nasze źródło danych nie zawiera ostatniej znanej lokalizacji, zwrócona zostanie wartość null.

	private void showLocation() {
		StringBuilder latitudeStr = new StringBuilder("Latitude:\n");
		StringBuilder longitudeStr = new StringBuilder("Longitude:\n");
		for (String providerStr : locationManager.getAllProviders()) {
			Location location = locationManager.getLastKnownLocation(providerStr);
			if (location != null) {
				latitudeStr.append(location.getLatitude());
				longitudeStr.append(location.getLongitude());
			} else {
				latitudeStr.append("null");
				longitudeStr.append("null");
			}
			latitudeStr.append(" from: " + providerStr + "\n");
			longitudeStr.append(" from: " + providerStr + "\n");
		}
		tvLatitude.setText(latitudeStr);
		tvLongitude.setText(longitudeStr);
	}

Zrzut ekranu

Kompletny kod źródłowy

MainActivity.java

package pl.froger.hello;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
	private TextView tvLatitude;
	private TextView tvLongitude;
	private TextView tvLocationProviders;

	private LocationManager locationManager;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		tvLatitude = (TextView) findViewById(R.id.tvLatitude);
		tvLongitude = (TextView) findViewById(R.id.tvLongitude);
		tvLocationProviders = (TextView) findViewById(R.id.tvLocationProviders);
		getLocationManager();
		showLocationProvidersInfo();
		showLocation();
	}

	private void getLocationManager() {
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
	}

	private void showLocationProvidersInfo() {
		String providers = getLocationProvidersInfo();
		tvLocationProviders.setText(providers);
	}

	private String getLocationProvidersInfo() {
		StringBuilder locationProviders = new StringBuilder();
		for (String providerName : locationManager.getAllProviders()) {
			locationProviders.append(providerName);
			locationProviders.append(" ");
			if (locationManager.isProviderEnabled(providerName))
				locationProviders.append("(enabled)");
			else
				locationProviders.append("(disable)");
			locationProviders.append("\n");
		}
		return locationProviders.toString();
	}

	private void showLocation() {
		StringBuilder latitudeStr = new StringBuilder("Latitude:\n");
		StringBuilder longitudeStr = new StringBuilder("Longitude:\n");
		for (String providerStr : locationManager.getAllProviders()) {
			Location location = locationManager.getLastKnownLocation(providerStr);
			if (location != null) {
				latitudeStr.append(location.getLatitude());
				longitudeStr.append(location.getLongitude());
			} else {
				latitudeStr.append("null");
				longitudeStr.append("null");
			}
			latitudeStr.append(" from: " + providerStr + "\n");
			longitudeStr.append(" from: " + providerStr + "\n");
		}
		tvLatitude.setText(latitudeStr);
		tvLongitude.setText(longitudeStr);
	}
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="center"
		android:textSize="20sp"
		android:text="Location Providers" />
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="---"
		android:id="@+id/tvLocationProviders" />
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Your coordinates"
		android:textSize="20sp"
		android:layout_gravity="center" />
	<TextView
		android:id="@+id/tvLatitude"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Latitude: " />
	<TextView
		android:id="@+id/tvLongitude"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Longitude: " />
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
	xmlns:android="http://schemas.android.com/apk/res/android"
	package="pl.froger.hello"
	android:versionCode="1"
	android:versionName="1.0">
	<uses-sdk android:minSdkVersion="8" />
	<application
		android:icon="@drawable/icon"
		android:label="@string/app_name">
		<activity
			android:name=".MainActivity"
			android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
	</application>
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Komentarze (1) Subskrybuj

 

Prześlij komentarz

Zaloguj się lub skorzystaj z profilu:

[rpxlogin redirect="http://www.android4devs.pl" prompt="" style="large"]

Możesz również zostawić komentarz bez rejestracji, korzystając z poniższego formularza:

Musisz być zalogowany aby móc pisać komentarze.