0

I've searched for days and days and somehow the answer to why onLocationChanged isn't being called has eluded me. I've read the documentation extensively and I MUST be missing something crucial. I simply want a service that runs in the background, when location has changed, I want to log the location.

Here's my service...

import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class BackgroundLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    private final String TAG = ((Object) this).getClass().getSimpleName();

    IBinder mBinder = new LocalBinder();

    GoogleApiAvailability googleAPI;
    PowerManager.WakeLock mWakeLock;
    private boolean mInProgress;
    private Boolean servicesAvailable = false;

    protected GoogleApiClient mGoogleApiClient;
    protected LocationRequest mLocationRequest;
    private Intent mIntentService;
    private PendingIntent mPendingIntent;

    public class LocalBinder extends Binder {
        public BackgroundLocationService getServerInstance() {
            return BackgroundLocationService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();

        googleAPI = GoogleApiAvailability.getInstance();
        mInProgress = false;

        mIntentService = new Intent(this,BackgroundLocationService.class);
        mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);

        servicesAvailable = servicesConnected();

        /*
         * Create a new google api client, using the enclosing class to handle callbacks.
         */
        buildGoogleApiClient();
    }

    private boolean servicesConnected() {

        // Check that Google Play services is available
        int resultCode = googleAPI.isGooglePlayServicesAvailable(this);

        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {

            return true;
        } else {

            return false;
        }
    }

    protected void startLocationUpdates() {
        Log.i(TAG, "Started Location Updates");
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
    }

    protected void stopLocationUpdates() {
        Log.i(TAG,"Stopped Location Updates");
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
    }

    protected void createLocationRequest() {
        Log.i(TAG, "createLocationRequest()");
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(1000);
        //mLocationRequest.setMaxWaitTime(10000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE); //*** added this

        if (this.mWakeLock == null) {
            mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "aWakeLock"); //*** added this
        }

        if (!this.mWakeLock.isHeld()) {
            mWakeLock.acquire(); //*** added this
        }

        if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
            return START_STICKY;

        if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) {
            Log.e(TAG, "Location Client not connected, connecting...");
            mInProgress = true;
            mGoogleApiClient.connect();
        }

        Log.e(TAG, "Location Client: onStartCommand");
        return START_STICKY;
    }

    protected synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building GoogleApiClient");
        if (mGoogleApiClient == null) {
            this.mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }
        createLocationRequest();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onDestroy() {
        // Turn off the request flag
        this.mInProgress = false;

        if (this.mWakeLock != null) {
            this.mWakeLock.release();
            this.mWakeLock = null;
        }

        Log.e(TAG, "Location Client: ON DESTROY");
        super.onDestroy();
        stopLocationUpdates();
    }

    @Override
    public void onConnected(Bundle bundle) {

        startLocationUpdates();
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.e(TAG, "Location Receiver [Location Changed]: " + location.getLatitude() + ", " + location.getLongitude());
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.e(TAG, "Location Client: ON CONNECTED");
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        mInProgress = false;

        Log.e(TAG, "Location Client: ON CONNECTION FAILED");
        if (connectionResult.hasResolution()) {

            // If no resolution is available, display an error dialog
        } else {

        }
    }
}

I'm starting the service like this...

Intent BackgroundLocationService = new Intent(this, BackgroundLocationService.class);
            startService(BackgroundLocationService);

I have the following permission in the manifest as well...

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Kit
  • 531
  • 3
  • 8

1 Answers1

1

The requestLocationUpdates uses a pendingintent currently which is fired to start the service again. This is not calling the OnLocationchanged callback. Try using the requestLocationUpdates with location listener (3rd parameter). It should call OnLocationchanged.

user1930106
  • 779
  • 1
  • 6
  • 19
  • That indeed fires onLocationChanged but it appears that I need to use the PendingIntent to make sure my service continues to run when the app is in the background. Check this out: https://uncorkedstudios.com/blog/background-location-updates-on-android ...with that said, I tried registering a broadcast receiver in the manifest along with actually implementing it just like the link I posted said to do...yet I receive no location change broadcasts (and yes, the location is changing). – Kit May 09 '16 at 19:23
  • If you are implementing the service by START_STICKY then android OS will restart the service if it ever gets terminated due to low memory. So make sure on resume, requestLocationUpdates starts again. Do not worry about pending intent (use case in different scenarios). You can upvote my answer if all is fine. – user1930106 May 09 '16 at 19:51
  • You didn't answer the question. Listeners are fired when using locationlisteners and they are for when your app needs location update while in the foreground. Pendingintent are used when you want to receive updates while your app is in the background also. [android documentation]('https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, android.app.PendingIntent)') – Phil Aug 08 '16 at 15:44