简体   繁体   中英

Service not receiving location updates

I have implemented a background service to receive location updates:

public class TestActivity extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static String TAG = TestActivity_backup.class.getName();
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

private LocationRequest mLocationRequest;    
GoogleApiClient mGoogleApiClient=null;


@Override
public void onCreate() {
    super.onCreate();
    if (!isGooglePlayServicesAvailable()) {
        stopSelf();
    }
    setContentView(R.layout.activity_test);

    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10000).setFastestInterval(5000).setSmallestDisplacement(20);        
    this.buildGoogleApiClient();

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.destination = intent.getStringExtra("DESTINATION");
    LatLng latLng = intent.getParcelableExtra("LOCATION");
    this.location = new Location("");
    this.location.setLatitude(latLng.latitude);
    this.location.setLongitude(latLng.longitude);

    return START_NOT_STICKY;
}

@Override
public void onLocationChanged(Location location){
    Toast.makeText(TestActivity.this, "User location changed", Toast.LENGTH_SHORT).show();        
}

@Override
public void onConnected(Bundle bundle) {
    Toast.makeText(TestActivity.this, "Location  service connected", Toast.LENGTH_SHORT).show();        
}   


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

@Override
public void onDestroy() {
    super.onDestroy();
}

@Override
public void onConnectionSuspended(int i) {
    Log.i(TAG, "Location services suspended. Please reconnect.");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    //TODO
}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}


private boolean isGooglePlayServicesAvailable() {
    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (ConnectionResult.SUCCESS == status) {
        return true;
    } else {
        //GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
        return false;
    }
}    

}

I have implemented all relevant methods.onCreate and onStartCommand are called but onConnec ted and onLocationChanged are never ever called.If I implement an activity for location updates then its working fine. What am I missing here?

Don't forget to add permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION depending upon Accuracy

And use this Code

public class LocationService extends Service {

    private LocationListener locationListener;

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

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        super.onStartCommand(intent, flags, startId);
        return Service.START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        this.locationListener = new MyLocationListener();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, this.locationListener);
    }

    private static class MyLocationListener implements LocationListener {

        @Override
        public void onLocationChanged(final Location location) {
        }

        @Override
        public void onProviderDisabled(final String provider) {
        }

        @Override
        public void onProviderEnabled(final String provider) {
        }

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

    }

}

Here is my code that worked for me!

Don't forget to add mgoogleApiClient.connect() in onCreate() and then take a look at the onConnected Method of googleapiClient - here I've created the the LocationRequest with

LocationServices.FusedLocationApi.requestLocationUpdates(
                    googleApiClient, mLocationRequest, this);

and then for testing I used

 LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

for the initial Request.

If you are using emulator don't forget to telnet localhost 5543 (to your emulator) and then use the command geo fix to set the initial location. You can test it with geofixing to another location then the onLocationChanged Methode should be called ...

 package com.pekam.androidservice;
    import java.text.DateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;

    import com.google.android.gms.common.GooglePlayServicesUtil;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.pekam.myandroidtheme.*;
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.location.Location;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.util.Log;
    import android.widget.Toast;

    import com.google.android.gms.location.*;
    import com.google.android.gms.location.LocationListener;

    public class MyService  extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,LocationListener  {

            private NotificationManager nm;
            private Timer timer = new Timer();
            private int counter = 0;
            private int incrementby = 1;
            private static boolean isRunning = false;
            private GoogleApiClient googleApiClient;
            private LocationRequest mLocationRequest = new LocationRequest();
            private String strLOG="LOG";


            ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
            int mValue = 0; // Holds last value set by a client.
            static final int MSG_REGISTER_CLIENT = 1;
            static final int MSG_UNREGISTER_CLIENT = 2;
            static final int MSG_SET_INT_VALUE = 3;
            static final int MSG_SET_STRING_VALUE = 4;
            static final int MSG_SET_STRING_LOG =5;

            final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.


        // LocationRequest
        @Override
        public void onLocationChanged(Location location) {
            Location mCurrentLocation = location;
            sendLogMessageToUI("Last Known Loc" + mCurrentLocation.getLongitude() + mCurrentLocation.getLatitude());
        }


        //GoogleApiClient
        @Override
        public void onConnectionFailed(ConnectionResult bundle) {

        }

        @Override
        public void onConnected(Bundle bundle) {
            Log.i("onConnected", "GoogleApiClient" );
            try {
                Toast.makeText(this, "Location  service connected", Toast.LENGTH_SHORT).show();

                createLocationRequest();
                LocationServices.FusedLocationApi.requestLocationUpdates(
                        googleApiClient, mLocationRequest, this);
                LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

            } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
                Log.e("Google APi Connected", "Google APi Connected Failed.", t);
            }
        }

        @Override
        public void onConnectionSuspended(int i) {

        }

        //Service
            @Override
            public void onCreate() {
                super.onCreate();
                Log.i("MyService", "Service Started.");
                showNotification();
                timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 1900L);
                isRunning = true;


                try {
                    googleApiClient =  new GoogleApiClient.Builder(this)

                           .addApi(LocationServices.API)
                           .addConnectionCallbacks(this)
                           .addOnConnectionFailedListener(this)

                           .build();

                    googleApiClient.connect();

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
            @Override
            public int onStartCommand(Intent intent, int flags, int startId) {
                Log.i("MyService", "Received start id " + startId + ": " + intent);
                return START_STICKY; // run until explicitly stopped.
            }
            @Override
            public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();
        }

        public static boolean isRunning()
            {
                return isRunning;
            }


        private void onTimerTick() {
                Log.i("TimerTick", "Timer doing work." + counter);
                try {
                    counter += incrementby;
                    sendMessageToUI(counter);
               //     LocationServices.FusedLocationApi.setMockMode(googleApiClient, true);
                  //  double latitude = LocationServices.FusedLocationApi.getLastLocation(googleApiClient).getLatitude();




                } catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
                    Log.e("TimerTick", "Timer Tick Failed.", t);            
                }
            }
        private boolean isGooglePlayServicesAvailable() {
            int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
            if (ConnectionResult.SUCCESS == status) {
                return true;
            } else {
                //GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
                return false;
            }
        }
        private void showNotification() {
            nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
            // In this sample, we'll use the same text for the ticker and the expanded notification
            CharSequence text = getText(R.string.service_started);
            // Set the icon, scrolling text and timestamp
            Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
            // The PendingIntent to launch our activity if the user selects this notification
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TabBarActivity.class), 0);
            // Set the info for the views that show in the notification panel.
            notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
            // Send the notification.
            // We use a layout id because it is a unique number.  We use it later to cancel.
            nm.notify(R.string.service_started, notification);
        }
        protected void createLocationRequest() {

            mLocationRequest.setInterval(10000);
            mLocationRequest.setFastestInterval(5000);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
        private void sendMessageToUI(int intvaluetosend) {
            for (int i=mClients.size()-1; i>=0; i--) {
                try {
                    // Send data as an Integer
                    mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0));

                    //Send data as a String
                    Bundle b = new Bundle();
                    b.putString("str1", "ab" + intvaluetosend + "cd");
                    Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
                    msg.setData(b);
                    mClients.get(i).send(msg);

                } catch (RemoteException e) {
                    // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
                    mClients.remove(i);
                }
            }
        }
        private void sendLogMessageToUI(String strLOG) {
            for (int i=mClients.size()-1; i>=0; i--) {
                try {
                    // Send data as an Integer
                    mClients.get(i).send(Message.obtain());
                    //Send data as a String
                    Bundle b = new Bundle();
                    b.putString("strLOG", strLOG);
                    Message msg = Message.obtain(null, MSG_SET_STRING_LOG);
                    msg.setData(b);
                    mClients.get(i).send(msg);

                } catch (RemoteException e) {
                    // The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
                    mClients.remove(i);
                }
            }
        }
        class IncomingHandler extends Handler { // Handler of incoming messages from clients.
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_REGISTER_CLIENT:
                        mClients.add(msg.replyTo);
                        break;
                    case MSG_UNREGISTER_CLIENT:
                        mClients.remove(msg.replyTo);
                        break;
                    case MSG_SET_INT_VALUE:
                        incrementby = msg.arg1;
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM