Get location with GPS
Description
The following code shows how to Get location with GPS.
Example
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.java2s.myapplication3.app" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="java2s.com"
android:theme="@style/AppTheme" >
<activity
android:name="com.java2s.myapplication3.app.MainActivity"
android:label="java2s.com"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Main layout xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginTop="5dp"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="30dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_marginTop="30dp"
android:text="GPS Events:"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/gps_events"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="1dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_marginTop="10dp"
android:text="GPS Satellite Status:"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/satellite_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="1dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</ScrollView>
</LinearLayout>
Main Activity Java code
package com.java2s.myapplication3.app;
/*w w w .java2 s . c o m*/
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.widget.TextView;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class MainActivity extends Activity {
public static final String LOC_DATA = "LOC_DATA";
private LocationManager locationMgr;
private GpsListener gpsListener;
private GpsStatus gpsStatus;
private Handler handler;
private TextView title;
private TextView detail;
private TextView gpsEvents;
private TextView satelliteStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
title = (TextView) findViewById(R.id.title);
detail = (TextView) findViewById(R.id.detail);
gpsEvents = (TextView) findViewById(R.id.gps_events);
satelliteStatus = (TextView) findViewById(R.id.satellite_status);
title.setText("Get current location via GPS");
detail.setText("Attempting to get current location...\n (may take a few seconds)");
locationMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
gpsListener = new GpsListener();
handler = new Handler() {
public void handleMessage(Message m) {
Log.d("log", "Handler returned with message: " + m.toString());
if (m.what == LocationHelper.MESSAGE_CODE_LOCATION_FOUND) {
detail.setText("HANDLER RETURNED\nlat:" + m.arg1 + "\nlon:" + m.arg2);
} else if (m.what == LocationHelper.MESSAGE_CODE_LOCATION_NULL) {
detail.setText("HANDLER RETURNED\nunable to get location");
} else if (m.what == LocationHelper.MESSAGE_CODE_PROVIDER_NOT_PRESENT) {
detail.setText("HANDLER RETURNED\nprovider not present");
}
}
};
}
@Override
protected void onResume() {
super.onResume();
// determine if GPS is enabled or not, if not prompt user to enable it
if (!locationMgr.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("GPS is not enabled")
.setMessage("Would you like to go the location settings and enable GPS?").setCancelable(true)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
LocationHelper locationHelper = new LocationHelper(locationMgr, handler, "log");
locationHelper.getCurrentLocation(30);
}
locationMgr.addGpsStatusListener(gpsListener);
}
@Override
protected void onPause() {
super.onPause();
locationMgr.removeGpsStatusListener(gpsListener);
}
// you can also use a GpsListener to be notified when the GPS is started/stopped, and when first "fix" is obtained
private class GpsListener implements GpsStatus.Listener {
public void onGpsStatusChanged(int event) {
Log.d("GpsListener", "Status changed to " + event);
switch (event) {
case GpsStatus.GPS_EVENT_STARTED:
gpsEvents.setText("GPS_EVENT_STARTED");
break;
case GpsStatus.GPS_EVENT_STOPPED:
gpsEvents.setText("GPS_EVENT_STOPPED");
break;
// GPS_EVENT_SATELLITE_STATUS will be called frequently
// all satellites in use will invoke it, don't rely on it alone
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
// this is *very* chatty, only very advanced use cases should need this (avoid it if you don't need it)
gpsStatus = locationMgr.getGpsStatus(gpsStatus);
StringBuilder sb = new StringBuilder();
for (GpsSatellite sat : gpsStatus.getSatellites()) {
sb.append("Satellite N:" + sat.getPrn() + " AZ:" + sat.getAzimuth() + " EL:" + sat.getElevation()
+ " S/N:" + sat.getSnr() + "\n");
}
satelliteStatus.setText(sb.toString());
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
gpsEvents.setText("GPS_EVENT_FIRST_FIX");
break;
}
}
}
}
/**
* Helper class to encapsulate some of the common code needed to determine the
* current location using FINE (GPS) provider.
* <p/>
* If the most recent location is available for the FINE provider, and it is relatively
* recent (within FIX_RECENT_BUFFER_TIME -- currently 30 seconds), it is returned back to
* the caller using a Message indicating the results.
* <p/>
* IF the most recent location is either not available, or too old to be used, the
* a LocationListener is kicked off for a specified duration. Once the LocationListener
* either gets a good Location update, or the time is elapsed, a Message is sent back
* to the caller indicating the results.
* <p/>
* Example usage from an Activity:
* <p/>
* <pre>
*
* Handler handler = new Handler() {
* public void handleMessage(Message m) {
* Log.d(LOG_TAG, "Handler returned with message: " + m.toString());
* if (m.what == LocationHelper.MESSAGE_CODE_LOCATION_FOUND) {
* Toast.makeText(Activity.this, "HANDLER RETURNED -- lat:" + m.arg1 + " lon:" + m.arg2, Toast.LENGTH_SHORT)
* .show();
* } else if (m.what == LocationHelper.MESSAGE_CODE_LOCATION_NULL) {
* Toast.makeText(Activity.this, "HANDLER RETURNED -- unable to get location", Toast.LENGTH_SHORT).show();
* } else if (m.what == LocationHelper.MESSAGE_CODE_PROVIDER_NOT_PRESENT) {
* Toast.makeText(Activity.this, "HANDLER RETURNED -- provider not present", Toast.LENGTH_SHORT).show();
* }
* }
* };
*
* LocationHelper helper = new LocationHelper(locationManager, handler, LOG_TAG);
* helper.getCurrentLocation(handler);
* </pre>
*
* @author ccollins
*/
class LocationHelper {
public static final int MESSAGE_CODE_LOCATION_FOUND = 1;
public static final int MESSAGE_CODE_LOCATION_NULL = 2;
public static final int MESSAGE_CODE_PROVIDER_NOT_PRESENT = 3;
private static final int FIX_RECENT_BUFFER_TIME = 30000;
private LocationManager locationMgr;
private LocationListener locationListener;
private Handler handler;
private Runnable handlerCallback;
private String providerName;
private String logTag;
/**
* Construct with a LocationManager, and a Handler to pass back Messages via.
*
* @param locationMgr
* @param handler
*/
public LocationHelper(LocationManager locationMgr, Handler handler, String logTag) {
this.locationMgr = locationMgr;
this.locationListener = new LocationListenerImpl();
this.handler = handler;
this.handlerCallback = new Thread() {
public void run() {
endListenForLocation(null);
}
};
Criteria criteria = new Criteria();
// use Criteria to get provider (and could use COARSE, but doesn't work in emulator)
// (FINE will use EITHER network/gps, whichever is the best enabled match, except in emulator must be gps)
// (NOTE: network won't work unless enabled - Settings->Location & Security Settings->Use wireless networks)
criteria.setAccuracy(Criteria.ACCURACY_FINE);
this.providerName = locationMgr.getBestProvider(criteria, true);
this.logTag = logTag;
}
/**
* Invoke the process of getting the current Location.
* Expect Messages to be returned via the Handler passed in at construction with results.
*
* @param durationSeconds amount of time to poll for location updates
*/
public void getCurrentLocation(int durationSeconds) {
if (this.providerName == null) {
// return 2/0/0 if provider is not enabled
Log.d(logTag, "Location provideName null, provider is not enabled or not present.");
sendLocationToHandler(MESSAGE_CODE_PROVIDER_NOT_PRESENT, 0, 0);
return;
}
// first check last KNOWN location (and if the fix is recent enough, use it)
// NOTE -- this does NOT WORK in the Emulator
// (if you send a DDMS "manual" time or geo fix, you get correct DATE,
// but fix time starts at 00:00 and seems to increment by 1 second each time sent)
// to test this section (getLastLocation being recent enough), you need to use a real device
Location lastKnown = locationMgr.getLastKnownLocation(providerName);
if (lastKnown != null && lastKnown.getTime() >= (System.currentTimeMillis() - FIX_RECENT_BUFFER_TIME)) {
Log.d(logTag, "Last known location recent, using it: " + lastKnown.toString());
// return lastKnown lat/long on Message via Handler
sendLocationToHandler(MESSAGE_CODE_LOCATION_FOUND, (int) (lastKnown.getLatitude() * 1e6),
(int) (lastKnown.getLongitude() * 1e6));
} else {
// last known is relatively old, or doesn't exist, use a LocationListener
// and wait for a location update for X seconds
Log.d(logTag, "Last location NOT recent, setting up location listener to get newer update.");
listenForLocation(providerName, durationSeconds);
}
}
private void sendLocationToHandler(int msgId, int lat, int lon) {
Message msg = Message.obtain(handler, msgId, lat, lon);
handler.sendMessage(msg);
}
private void listenForLocation(String providerName, int durationSeconds) {
locationMgr.requestLocationUpdates(providerName, 0, 0, locationListener);
handler.postDelayed(handlerCallback, durationSeconds * 1000);
}
private void endListenForLocation(Location loc) {
locationMgr.removeUpdates(locationListener);
handler.removeCallbacks(handlerCallback);
if (loc != null) {
sendLocationToHandler(MESSAGE_CODE_LOCATION_FOUND, (int) (loc.getLatitude() * 1e6), (int) (loc.getLongitude() * 1e6));
} else {
sendLocationToHandler(MESSAGE_CODE_LOCATION_NULL, 0, 0);
}
}
private class LocationListenerImpl implements LocationListener {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(logTag, "Location status changed to:" + status);
switch (status) {
case LocationProvider.AVAILABLE:
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
break;
case LocationProvider.OUT_OF_SERVICE:
endListenForLocation(null);
}
}
@Override
public void onLocationChanged(Location loc) {
if (loc == null) {
return;
}
Log.d(logTag, "Location changed to:" + loc.toString());
endListenForLocation(loc);
}
@Override
public void onProviderDisabled(String provider) {
endListenForLocation(null);
}
@Override
public void onProviderEnabled(String provider) {
}
}
}