Search code examples
androidgpslocation

How can I get continuous location updates in Android like in Google Maps?


I'm building a friend tracking android app. While my friend activated the app and goes away along with his GPS and cellular data on, I need to track him on my device. That's the concept.

I've implemented LocationListener class and now I can get the last updated location either from Gps or Network but is not updated unless I launch Google Maps and return to my application. After googling, I learned that location cache is updated only by GMaps.!

  1. Is there an alternate way to continuously update location?
  2. What if when I need to get continues location after the device locked without making use of Wakelock?

This is my location listener class:

package com.amazinginside;

/** AMAZING LOCATION SUPPORT CLASS, Devoloped By SANGEETH NANDAKUMAR */

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;

public class AmazingLocation extends Service implements LocationListener
{
    private final Context mContext;
    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    boolean canGetLocation = false;

    Location location;
    double latitude=0.0;
    double longitude=0.0;

    //MINIMUM DISTANCE FOR UPDATE (meters)
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 Meters

    //MINIMUM TIME BETWEEN UPDATES
    private static final long MIN_TIME_BW_UPDATES = 1000 * 0; // 0 Seconds

    //LOCATION MANAGER
    protected LocationManager locationManager;

    //CONSTRUCTOR
    public AmazingLocation(Context context)
    {
        this.mContext = context;
        getLocation();
    }

    //LOCATION PROVISION
    public Location getLocation()
    {
        try
        {
            //GET LOCATION MANAGER
            locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
            //CHECK GPS STATE
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            //CHECK NETWORK STATE
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled)
            {
                //NO LOCATION PROVIDERS
            }
            else
            {
                this.canGetLocation = true;

                /** GET LOCATION FROM NETWORK */
                //FIRST GET LOCATION FROM NETWORK
                if (isNetworkEnabled)
                {
                    //REQUEST LOCATION
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    if (locationManager != null)
                    {
                        //START WITH LAST KNOWN LOCATION
                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        //EXTRACT LOCATION
                        if (location != null)
                        {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }

                /** GET LOCATION FROM GPS SENSOR */
                //THEN GET LOCATION FROM GPS
                if (isGPSEnabled)
                {
                    if (location == null)
                    {
                        //REQUEST GPS LOCATION
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                        if (locationManager != null)
                        {
                            //EXTRACT LAST KNOWN LOCATION
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            //RETURN LOCATION
                            if (location != null)
                            {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return location;
    }

    //STOP GPS SENSOR
    public void stopUsingGPS()
    {
        if(locationManager != null)
        {
            locationManager.removeUpdates(AmazingLocation.this);
        }
    }

    //EXTRACT LATTITUDE
    public double getLatitude()
    {
        if(location != null)
        {
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }

    //EXTACT LONGITUDE
    public double getLongitude()
    {
        if(location != null)
        {
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    //CAN I GET THE LOCATION.?
    public AmazingStatus canGetLocation()
    {
        AmazingStatus status=new AmazingStatus();
        if(this.canGetLocation)
        {
            status.setStatus(true);
            status.setErrorcode(0);
            status.setErrormsg("Task completed");
        }
        else
        {
            status.setStatus(false);
            status.setErrorcode(145);
            status.setErrormsg("Please turn on GPS access manually");
        }
        return status;
    }

    //SHOW LOCATION SETTINGS
    public AmazingStatus showSettingsAlert()
    {
        final AmazingStatus status=new AmazingStatus();
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
        alertDialog.setTitle("REQUIRES LOCATION ACCESS");
        alertDialog.setMessage("Please allow GPS access to this app");

        //POSSITIVE REPLY
        alertDialog.setPositiveButton("Allow", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog,int which)
            {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
                status.setStatus(true);
                status.setErrorcode(0);
                status.setErrormsg("Task completed");
            }
        });

        //NEGATIVE REPLY
        alertDialog.setNegativeButton("Deny", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                status.setStatus(false);
                status.setErrorcode(408);
                status.setErrormsg("User denied permission");
                dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
        return status;
    }

    //UNUSED OVERRIDE METHORDS...
    @Override
    public void onLocationChanged(Location location)
    {
        getLocation();
    }

    @Override
    public void onProviderDisabled(String provider)
    {
    }

    @Override
    public void onProviderEnabled(String provider)
    {
        getLocation();
    }

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

    @Override
    public IBinder onBind(Intent arg0)
    {
        return null;
    }

}

This my onCreate() method:

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //CREATE A BUTTON HANDLER
    Button start_btn=(Button)findViewById(R.id.start_location_streaming);
    //ON BUTTON CLICK EVENT
    start_btn.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            //REPEAT A METHORD AT SPECIFIC INTERVALS
            Timer myTimer = new Timer();
            myTimer.schedule(new TimerTask()
            {
                @Override
                public void run()
                {
                    TimerMethod();
                }

            }, 0, 8000);
        }
    });  }

These are other methods:

private void TimerMethod()
{
    //START METHORD
    this.runOnUiThread(Timer_Tick);
}

//LOCATION REPORTING METHORD
private Runnable Timer_Tick = new Runnable()
{
    public void run()
    {
        Toast.makeText(MainActivity.this, "Current latitude : "+Double.toString(getLocation().latitude), Toast.LENGTH_SHORT).show();
        Toast.makeText(MainActivity.this, "Current longitude : "+Double.toString(getLocation().longitude), Toast.LENGTH_SHORT).show();
    }
};

private LatLng getLocation()
{
    //CREATE A LOCATION CLASS INSTANCE
    AmazingLocation gps = new AmazingLocation(this);
    //RETRIVE LOCATION
    double latitude = gps.getLatitude();
    double longitude = gps.getLongitude();
    //RETURN LOCATION
    LatLng loc=new LatLng(latitude,longitude);
    return loc;
}  

Now the problem is, the toast just shows previously known the location and not updating unless I opened Google Maps and returned.

Any help will be great for me.


Solution

  • Use Fused location provider in Android set your interval in that:

    For an example create your activity like this:

    public class LocationActivity extends Activity implements
            LocationListener,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {
    
        private static final String TAG = "LocationActivity";
        private static final long INTERVAL = 1000 * 10;
        private static final long FASTEST_INTERVAL = 1000 * 5;
        Button btnFusedLocation;
        TextView tvLocation;
        LocationRequest mLocationRequest;
        GoogleApiClient mGoogleApiClient;
        Location mCurrentLocation;
        String mLastUpdateTime;
    
        protected void createLocationRequest() {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(INTERVAL);
            mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate ...............................");
            //show error dialog if GoolglePlayServices not available
            if (!isGooglePlayServicesAvailable()) {
                finish();
            }
            createLocationRequest();
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
    
            setContentView(R.layout.activity_main);
            tvLocation = (TextView) findViewById(R.id.tvLocation);
    
            btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
            btnFusedLocation.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    updateUI();
                }
            });
    
        }
    
        @Override
        public void onStart() {
            super.onStart();
            if (mGoogleApiClient.isConnected()) {
                startLocationUpdates();
                Log.d(TAG, "Location update resumed .....................");
            }
        }
    
        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, "onStop fired ..............");
            mGoogleApiClient.disconnect();
            Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
        }
    
        private boolean isGooglePlayServicesAvailable() {
            int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
            if (ConnectionResult.SUCCESS == status) {
                return true;
            } else {
                GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
                return false;
            }
        }
    
        @Override
        public void onConnected(Bundle bundle) {
            Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
            startLocationUpdates();
        }
    
        protected void startLocationUpdates() {
            PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
                    mGoogleApiClient, mLocationRequest, this);
            Log.d(TAG, "Location update started ..............: ");
        }
    
        @Override
        public void onConnectionSuspended(int i) {
    
        }
    
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Log.d(TAG, "Connection failed: " + connectionResult.toString());
        }
    
        @Override
        public void onLocationChanged(Location location) {
            Log.d(TAG, "Firing onLocationChanged..............................................");
            mCurrentLocation = location;
            mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
            updateUI();
        }
    
        private void updateUI() {
            Log.d(TAG, "UI update initiated .............");
            if (null != mCurrentLocation) {
                String lat = String.valueOf(mCurrentLocation.getLatitude());
                String lng = String.valueOf(mCurrentLocation.getLongitude());
                tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
                        "Latitude: " + lat + "\n" +
                        "Longitude: " + lng + "\n" +
                        "Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
                        "Provider: " + mCurrentLocation.getProvider());
            } else {
                Log.d(TAG, "location is null ...............");
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            stopLocationUpdates();
        }
    
        protected void stopLocationUpdates() {
            LocationServices.FusedLocationApi.removeLocationUpdates(
                    mGoogleApiClient, this);
            Log.d(TAG, "Location update stopped .......................");
        }
    
        @Override
        public void onResume() {
            super.onResume();
            if (mGoogleApiClient.isConnected()) {
                startLocationUpdates();
                Log.d(TAG, "Location update resumed .....................");
            }
        }
    }
    

    Google play services required: