How to receive location updates every 5 minutes using the FusedLocation API

后端 未结 2 1662
花落未央
花落未央 2021-02-06 18:14

I am currently working on an app that has to check the user\'s location every five minutes and send the coordinates to a server. I decided to go with the FusedLocation API in Go

2条回答
  •  死守一世寂寞
    2021-02-06 18:58

    I am currently working on an app that has to check the user's location every five minutes and send the coordinates to a server. I decided to go with the FusedLocation API in Google Play Services instead of the plain old LocationManager API

    Our app has exactly that same requirement, I implemented that a couple of days ago and here is how I did it.

    In the launch activity or wherever you want to start, configure a LocationTracker to run every 5 minutes, using an AlarmManager.

    private void startLocationTracker() {
        // Configure the LocationTracker's broadcast receiver to run every 5 minutes.
        Intent intent = new Intent(this, LocationTracker.class);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(),
                LocationProvider.FIVE_MINUTES, pendingIntent);
    }
    

    LocationTracker.java

    public class LocationTracker extends BroadcastReceiver {
    
        private PowerManager.WakeLock wakeLock;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            PowerManager pow = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            wakeLock = pow.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
            wakeLock.acquire();
    
            Location currentLocation = LocationProvider.getInstance().getCurrentLocation();
    
            // Send new location to backend. // this will be different for you
            UserService.registerLocation(context, new Handlers.OnRegisterLocationRequestCompleteHandler() {
                @Override
                public void onSuccess() {
                    Log.d("success", "UserService.RegisterLocation() succeeded");
    
                    wakeLock.release();
                }
    
                @Override
                public void onFailure(int statusCode, String errorMessage) {
                    Log.d("error", "UserService.RegisterLocation() failed");
                    Log.d("error", errorMessage);
    
                    wakeLock.release();
                }
            }, currentLocation);
        }
    }
    

    LocationProvider.java

    public class LocationProvider {
    
        private static LocationProvider instance = null;
        private static Context context;
    
        public static final int ONE_MINUTE = 1000 * 60;
        public static final int FIVE_MINUTES = ONE_MINUTE * 5;
    
        private static Location currentLocation;
    
        private LocationProvider() {
    
        }
    
        public static LocationProvider getInstance() {
            if (instance == null) {
                instance = new LocationProvider();
            }
    
            return instance;
        }
    
        public void configureIfNeeded(Context ctx) {
            if (context == null) {
                context = ctx;
                configureLocationUpdates();
            }
        }
    
        private void configureLocationUpdates() {
            final LocationRequest locationRequest = createLocationRequest();
            final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
                    .addApi(LocationServices.API)
                    .build();
    
            googleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                @Override
                public void onConnected(Bundle bundle) {
                    startLocationUpdates(googleApiClient, locationRequest);
                }
    
                @Override
                public void onConnectionSuspended(int i) {
    
                }
            });
            googleApiClient.registerConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                @Override
                public void onConnectionFailed(ConnectionResult connectionResult) {
    
                }
            });
    
            googleApiClient.connect();
        }
    
        private static LocationRequest createLocationRequest() {
            LocationRequest locationRequest = new LocationRequest();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(FIVE_MINUTES);
            return locationRequest;
        }
    
        private static void startLocationUpdates(GoogleApiClient client, LocationRequest request) {
            LocationServices.FusedLocationApi.requestLocationUpdates(client, request, new com.google.android.gms.location.LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    currentLocation = location;
                }
            });
        }
    
        public Location getCurrentLocation() {
            return currentLocation;
        }
    }
    

    I first create an instance of the LocationProvider in a class that extends application, creating the instance when the app is launched:

    MyApp.java

    public class MyApp extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            LocationProvider locationProvider = LocationProvider.getInstance();
            locationProvider.configureIfNeeded(this);
        }
    }
    

    The LocationProvider is instantiated and configured for location updates exactly once, because it is a singleton. Every 5 minutes it will update its currentLocation value, which we can retrieve from anywhere we need with

    Location loc = LocationProvider.getInstance().getCurrentLocation();
    

    Running a background service of any kind is not required. The AlarmManager will broadcast to LocationTracker.onReceive() every 5 minutes and the partial wakelock will ensure that the code will finish running even if the device is standby. This is also energy efficient.

    Note that you need the following permissions

    
    
    
    
    
    

    and don't forget to register the receiver:

    
    

提交回复
热议问题