Android Location API - Simple Location

Aus Wikizone
Wechseln zu: Navigation, Suche

Einleitung

Projekt

1. Android Projekt erstellen Name: Simple Location

Permissions

Zum manifest.xml hinzufügen:

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

Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dip"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/TextView01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Latitude: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@+id/TextView02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/TextView03"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="5dip"
            android:text="Longitute: "
            android:textSize="20dip" >
        </TextView>

        <TextView
            android:id="@+id/TextView04"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="unknown"
            android:textSize="20dip" >
        </TextView>
    </LinearLayout>

</LinearLayout>

ShowLocation Activity programmieren

1. Einen LocationListener implementieren

import android.location.LocationListener;
...
public class ShowLocationActivity extends Activity implements LocationListener  {
...

Eclipse zeigt daß wir für das Interface diverse Funktionen brauchen:

	@Override
	public void onLocationChanged(Location arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onProviderDisabled(String arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onProviderEnabled(String arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
		// TODO Auto-generated method stub
		
	}

Dann verdrahten wir die Textfelder des Layouts mit dem Code...

public class ShowLocationActivity extends Activity implements LocationListener{
	private TextView latitudeField;
	private TextView longitudeField;
	private LocationManager locationManager;
	private String provider;
...

	// activity is created...
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_show_location);
		latitudeField = (TextView) findViewById(R.id.TextView02);
		longitudeField = (TextView) findViewById(R.id.TextView04);
...

bei den Textviews haben wir auch schon einen LocationManager definiert und einen String, der den gewählten Provider speichern wird (gps oder network). Auch dieser wird in onCreate instanziiert:

LocationManager Service holen

locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Ein Criteria Objekt erstellen daß unsere Bedingungen an den Service enthält. Da wir nichts setzen sind es hier Standardbedingungen.

Criteria criteria = new Criteria();

Wir Fragen den Location Manager welches der beste Provider für unsere Kriterien sind (false -> auch wenn diese abgeschaltet sind).

provider = locationManager.getBestProvider(criteria, false);

Welches war die letzte bekannte Position ? Diese wir in ein Location Objekt gespeichert.

Location location = locationManager.getLastKnownLocation(provider);

Wenn wir was haben schreiben wir es in die Textfelder.

if(location != null){
	System.out.println("Provider " + provider + "has been selected.");
	onLocationChanged(location);
}else{
	tvLatitude.setText("Location is not available");
	tvLongitude.setText("Location is not available");
}

Wenn die Activity startet (oder resumed wird) soll der LocationManager regelmäßig Updates über den gewählten provider liefern. Es sollen aber mindestens 600ms und 10m zwischen den Updates liegen. Damit wir dann auch etwas übernehmen können wird im letzten Parameter ein locationManager übergeben dessen onLocationChanged Methode aufgerufen werden soll. In diesem Fall übergeben wir ihn sich selbst.

	/* Request updates at startup */
	@Override
	protected void onResume() {
	  super.onResume();
	  locationManager.requestLocationUpdates(provider, 600, 10, this);
	}

Wenn die Activity pausiert sollen auch die Updates pausieren

	/* locationlistener updates stoppen wenn Activity pausiert sonst gibt es Fehler im Log */
	@Override
	protected void onPause() {
		super.onPause();
		locationManager.removeUpdates(this);
	}

Wenn eine neue Position kommt -> Felder updaten:

	@Override
	public void onLocationChanged(Location location) {
	    int lat = (int) (location.getLatitude());
	    int lng = (int) (location.getLongitude());
	    tvLatitude.setText(String.valueOf(lat));
	    tvLongitude.setText(String.valueOf(lng));
	}

Code Variante

In diesem Beispiel implementiert nicht die Activity das LocationListener Interface, sondern wir nutzen eine separate Klasse LocListenerDisplay, die für den LocationListener und das Anzeigen der Daten zuständig ist.

Dies sorgt für bessere Trennung der Aufgaben und besser wartbaren Code.

package de.webmynet.android.simplelocation;

//import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
//import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class ShowLocationActivity extends Activity{
	private TextView tvLatitude;
	private TextView tvLongitude;
	private LocationManager locManager;
	private LocationListener locListenD; //locationListenerDisplay
	private String provider;
	private Context myContext;

	// activity is created...
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_show_location);
		myContext = this;
		// Text Views abrufen
		tvLatitude = (TextView) findViewById(R.id.TextView02);
		tvLongitude = (TextView) findViewById(R.id.TextView04);
		
		// LocationManager Service Handle holen
		locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Location loc = locManager.getLastKnownLocation("gps");
		
		//TVs setzen
		if(loc != null){
		    float lat = (float) (loc.getLatitude());
		    float lng = (float) (loc.getLongitude());
		    tvLatitude.setText(String.valueOf(lat));
		    tvLongitude.setText(String.valueOf(lng));
		}else{
			tvLatitude.setText("Location is not available");
			tvLongitude.setText("Location is not available");
		}
		
		// LocationListenerDisplay Objekt initialisieren
		locListenD = new LocListenerDisplay();
	}
	
	private class LocListenerDisplay implements LocationListener{
		@Override
		public void onLocationChanged(Location loc) {
		    float lat = (float) (loc.getLatitude());
		    float lng = (float) (loc.getLongitude());
		    tvLatitude.setText(String.valueOf(lat));
		    tvLongitude.setText(String.valueOf(lng));
		}

		@Override
		public void onProviderDisabled(String provider) {
			Toast.makeText(myContext,  "onProviderDisabled - disabled provider", Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onProviderEnabled(String provider) {
			Toast.makeText(myContext,  "onProviderEnebled - New provider: " + provider, Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	}

	/* Location updates liefern wenn die Activity (neu-)startet */
	@Override
	protected void onResume() {
		super.onResume();
		Toast.makeText(this,  "RESUME - selected provider: " + provider, Toast.LENGTH_SHORT).show();
		locManager.requestLocationUpdates("gps", 600, 20, locListenD);
	}
	
	/* locationlistener updates stoppen wenn Activity pausiert sonst gibt es Fehler im Log */
	@Override
	protected void onPause() {
		super.onPause();
		locManager.removeUpdates(locListenD);
	}
}