Android How to - Get location with GPS








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;
/*  ww  w. j a  va  2  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) {
        }
    }
}
null