2

I want to create that I send every few seconds a message to GCM. But after some time I want to remove the locationupdates again. For sending the data to the intentservice of gcm I use a pendingintent. Now every time and it happens a lot I get this error :

Caused by:

java.lang.IllegalStateException: GoogleApiClient is not connected yet.
            at com.google.android.gms.common.internal.n.a(Unknown Source)
            at com.google.android.gms.common.api.b.b(Unknown Source)
            at com.google.android.gms.internal.lt.removeLocationUpdates(Unknown Source)
            at com.example.task_1.Location.LocationUpdate.stopLocationUpdates(LocationUpdate.java:83)
            at com.example.task_1.Location.LocationUpdate.onStartCommand(LocationUpdate.java:52)
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2704)
            at android.app.ActivityThread.access$1900(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

This is my code:

public class LocationUpdate extends Service implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {
    private static final String TAG = "DRIVER";
    private SharedPreferences pref;
    private String driverId;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private Intent mGcmIntentService;
    private PendingIntent mPendingIntent;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        boolean stopService = false;
        if (intent != null)
            stopService = intent.getBooleanExtra("stopservice", false);
        if (stopService)
            stopLocationUpdates();
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
        pref = getSharedPreferences("driver_app", MODE_PRIVATE);
        driverId = pref.getString("driver_id", "");
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();

    }

    public void stopLocationUpdates() {
        if(!mGoogleApiClient.isConnected()){
            mGoogleApiClient.connect();
        }
        mGcmIntentService = new Intent(this,SendDataIntentService.class);
        mGcmIntentService.putExtra("ID", "FusedLocation");
        mPendingIntent = PendingIntent.getService(this, 0, mGcmIntentService, PendingIntent.FLAG_CANCEL_CURRENT);
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
        if (mGoogleApiClient.isConnected())
            mGoogleApiClient.disconnect();
    }
    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void onConnected(Bundle arg0) {
        // TODO Auto-generated method stub
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setInterval(30000);
        startLocationUpdates();
    }
    private void startLocationUpdates() {
        mGcmIntentService = new Intent(this,SendDataIntentService.class);
        mGcmIntentService.putExtra("ID", "FusedLocation");
        mPendingIntent = PendingIntent.getService(this, 0, mGcmIntentService, PendingIntent.FLAG_CANCEL_CURRENT);
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
    }

    @Override
    public void onConnectionSuspended(int arg0) {
        // TODO Auto-generated method stub

    }

}

Anyone know how to solve this bug? Or how to fix it? I searched on the internet but can't find anything.

Tim Dirks
  • 35
  • 1
  • 5
  • I'm on my phone now and so can't see line numbers. But at line 83 of your code the client isn't connected. Look into blocking until there's a connection (don't block the ui thread though) – David M May 31 '15 at 20:18
  • Can you be more specific, how can I check till there is a connection? Implementing a while loop? Or can you hint me up with a better solution? – Tim Dirks May 31 '15 at 20:26

1 Answers1

1

The problem is that in your stopLocationUpdates() method, you are not waiting for the API to be connected before you call removeLocationUpdates().

One simple way to fix this would be to set a boolean flag when you need to remove location callbacks, but the API is not connected.

Add a member variable:

private boolean isRemoving = false;

Then modify the logic so that it waits for the API to connect before unregistering for location callbacks.

In the stopLocationUpdates() method:

public void stopLocationUpdates() {
    if(!mGoogleApiClient.isConnected()){
        isRemoving = true; //added
        mGoogleApiClient.connect();
    }
    else {
        mGcmIntentService = new Intent(this, SendDataIntentService.class);
        mGcmIntentService.putExtra("ID", "FusedLocation");
        mPendingIntent = PendingIntent.getService(this, 0, mGcmIntentService, PendingIntent.FLAG_CANCEL_CURRENT);
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
        if (mGoogleApiClient.isConnected())
            mGoogleApiClient.disconnect();
    }
}

In the onConnected() callback:

@Override
public void onConnected(Bundle arg0) {

    if (isRemoving){
        stopLocationUpdates();
    }
    else {
        // TODO Auto-generated method stub
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setInterval(30000);
        startLocationUpdates();
    }
}

You would also want to set the flag back to false in startLocationUpdates():

private void startLocationUpdates() {
    isRemoving = false; //added
    mGcmIntentService = new Intent(this,SendDataIntentService.class);
    mGcmIntentService.putExtra("ID", "FusedLocation");
    mPendingIntent = PendingIntent.getService(this, 0, mGcmIntentService, PendingIntent.FLAG_CANCEL_CURRENT);
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
}

Also in onCreate():

@Override
public void onCreate() {
    Log.e(TAG, "onCreate");
    isRemoving = false; //added
    pref = getSharedPreferences("driver_app", MODE_PRIVATE);
    driverId = pref.getString("driver_id", "");
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API).addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this).build();
    mGoogleApiClient.connect();
}

Edit: To re-start the location callbacks after they have been previously cancelled, you can use the onStartCommand() method.

Modify onStartCommand() so that it can both stop and start location updates:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e(TAG, "onStartCommand");
    super.onStartCommand(intent, flags, startId);
    boolean stopService = false;
    if (intent != null) {
        stopService = intent.getBooleanExtra("stopservice", false);
    }

    if (stopService) {
        stopLocationUpdates();
    }
    else{
        isRemoving = false;
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        mGoogleApiClient.connect();
    }
    return START_STICKY;
}

Then, in order to re-start location updates, you would call startService() with an Intent that has stopservice set to false:

    Intent i = new Intent(this, LocationUpdate.class);
    i.putExtra("stopservice", false);
    startService(i);
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • It still gives me some errors... I can't figure out why, but sometimes it works sometimes don't. I start and stop it when a user clicks a button on the UI. – Tim Dirks Jun 01 '15 at 09:23
  • When I call it for the first thim, the locations are send. Then I remove them and after that when I want to send back locations the oncreate and onconnected is not called anymore. – Tim Dirks Jun 01 '15 at 10:02
  • @TimDirks I just updated the answer, let me know if that works for you! – Daniel Nugent Jun 01 '15 at 16:57
  • Thanks for the quick replay, do you know maybe aswell if I fill in a timeinterval of 900 000 (means sending data every 15 minutes) , but it sends the data every 4 minutes? Do I need to include something more specific? – Tim Dirks Jun 01 '15 at 17:11
  • @TimDirks Sure, no problem! If I understand correctly, it sounds like you should use the `setFastestInterval()` method in your `LocationRequest`. From the documentation: `If you don't call this method, a fastest interval will be selected for you. It will be a value faster than your active interval ` See documentation here: https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest#setFastestInterval(long) example: http://stackoverflow.com/questions/30191047/access-coarse-location-permission-gives-a-cell-tower-precision-on-android/30315009#30315009 – Daniel Nugent Jun 01 '15 at 17:29
  • @DanielNugent Thank you so much sir for clearing doubt. But I have one problem. After closing 1 service I am again starting 2 service but Its not starting. I followed all your steps. Yes GoogleClientApi not yet connected Crashed has been solved but How can I again start Service ? – coder_baba Jan 05 '18 at 08:18