Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to change update interval? #54

Closed
jsdevjournal opened this issue Jul 7, 2015 · 9 comments
Closed

Is it possible to change update interval? #54

jsdevjournal opened this issue Jul 7, 2015 · 9 comments

Comments

@jsdevjournal
Copy link

Hi, is it possible to change update location interval dynamically?

For some stage of the app I want it update like every 10 minutes, but some stage i need it to be like close to real- time.

Thank in advance!

@mcharmas
Copy link
Owner

mcharmas commented Jul 8, 2015

Hi, this libarary is only a wrapper on Google Play Services so you probably have to use LocationRequest to setup or change update interval.

@sytolk
Copy link
Contributor

sytolk commented Jul 9, 2015

The question is if its need to have 2 LocationRequest one with slow intervals like 10 min and other LocationRequest object with faster location update intervals like 5 seconds. And to switch between intervals to unsubscribe old and make new subscription with other LocationRequest. Or its enough to have only one subscription with saved LocationRequest instance and to set new interval. You can test the last. If GMS not copy initial LocationRequest it will work..

@lordlinus
Copy link

Hi, I tried to implement dynamic interval as below, but i am not sure if i go the google play services part wrong or the Rx part wrong.
GPS is turned on for the first time, but i dont think the interval is changed based on the activity
Any thought or advice?

MyLocation class

     public MyLocation(Context context) {
         this.context = context;
         startLocationSensor();
     }

     public static MyLocation getInstance(Context context) {
         if ( instance == null){
             Log.i(TAG,"creating new Location sensor");
             instance = new MyLocation(context);
         }
         return instance;
     }


    public void startLocationSensor(){

        locationProvider = new ReactiveLocationProvider(context);

        locationRequest = LocationRequest.create()
              .setFastestInterval(1000 * 10) //Do not receive the updated any frequent than 10 sec
              .setInterval(1000 * 20) // Receive location update every 20 sec
              .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)

        lastKnownLocationObservable = locationProvider
                .getLastKnownLocation()
                .subscribeOn(Schedulers.newThread())
                .observeOn(Schedulers.newThread());

        activityObservable = locationProvider
                .getDetectedActivity(1000 * 5);
        / * setter and getter for the location interval * /
          public void setLocationRequestInterval(long locationRequestInterval) {
            this.locationRequest.setInterval(locationRequestInterval);
        }

          public long getLocationRequestInterval() {
              return this.locationRequest.getInterval();
          }

    }

In my Service

    public void onCreate() {
        myLocation = MyLocation.getInstance(getApplicationContext());
        startObserving();
    }
    public void startObserving() {

      Observable<JSONObject>  o1 = /* Accelerometer Sensor obeservable  */

      Observable<JSONObject> o2 = myLocation.getActivityObservable()
            .observeOn(Schedulers.newThread())
            .map(new ToMostProbableActivity())
            .map(new DetectedActivityToJson())
            .doOnError(new ErrorHandler());

      Observable<JSONObject> o3 = myLocation.getLocationUpdatesObservable()
            .observeOn(Schedulers.newThread())
            .map(new LocationToJsonFunc())
            .doOnError(new ErrorHandler());


    r = Observable.combineLatest(o1, o2, o3, new Func4<JSONObject, JSONObject, JSONObject, JSONObject>() {
            @Override
            public JSONObject call(JSONObject s1, JSONObject s2, JSONObject s3) {
                return someCombinedJsonObject
            }
        }).filter(new Func1<JSONObject, Boolean>() {
                  @Override
                  public Boolean call(JSONObject jsonObject) {
                      acty = "get current activity from jsonObject"
                      float LocationRequestInterval = myLocation.getLocationRequestInterval();

                      if (acty.equalsIgnoreCase("still")) {
                          sendMessage = false; // Not interested in these message
                          if (LocationRequestInterval ==1000*5){
                              Log.d(TAG,"Dont need frequent updates, set to longer interval");
                              myLocation.setLocationRequestInterval(1000 * 60 * 15); // 15 minutes
                          }

                      } else {
                          if (LocationRequestInterval == 1000*60*15){
                              Log.d(TAG,"user is moving so need  frequent updates");
                              myLocation.setLocationRequestInterval(1000 * 5); // Every 5 seconds
                          }

                      }
                      return sendMessage;
                  }
              }
    );




    //subscribe to the combined observable and perform update
    combinedDataSubscription = r
            .sample(5, TimeUnit.SECONDS)
            .subscribe(new Action1<JSONObject>() {
                           @Override
                           public void call(JSONObject resultJson) {
                                  doSomethingwithData(resultJson);
                           }
                       }

            );

    }

@mcharmas
Copy link
Owner

I think the problem is that when you change location request settings you need to resubscribe to Google Play Services with updated location request.

@lordlinus
Copy link

@mcharmas can you please provide an example code?

@saiimons
Copy link

@lordlinus Look at my advice on #67 : using switchOnNext would work, without changing the subscriber.

@teresaholfeld
Copy link

@saiimons Could you provide an example? Your suggestion sounds nice, but I don't quite understand how to do it.

@thekalinga
Copy link

thekalinga commented Sep 29, 2016

@mcharmas

I have just modified the source of LocationUpdatesObservable to return LocationUpdateReconfigurableObservable instead of Observable<Location>

LocationUpdateReconfigurableObservable extends Observable<Location> & have a public method reconfigure(LocationRequest) which internally removes existing updates from api client & request fresh updates from GoogleApiClient with the new request passed. User can use this object to reconfigure location without worrying about managing his own version of GoogleApiClient

Whats your view on this change?

public class LocationUpdatesObservable extends BaseLocationObservable<Location> {

    private static final String TAG = LocationUpdatesObservable.class.getSimpleName();

    public static LocationUpdateReconfigurableObservable createObservable(Context ctx, LocationRequest locationRequest) {
        return new LocationUpdateReconfigurableObservable(new LocationUpdatesObservable(ctx, locationRequest));
    }

    private LocationRequest locationRequest;
    private LocationListener listener;
    private GoogleApiClient apiClient;
    private Observer<? super Location> observer;
    private AtomicBoolean wasGoogleClientReady = new AtomicBoolean(false);

    private LocationUpdatesObservable(Context ctx, LocationRequest locationRequest) {
        super(ctx);
        this.locationRequest = locationRequest;
    }

    @Override
    protected void onGoogleApiClientReady(GoogleApiClient apiClient, final Observer<? super Location> observer) {
        this.apiClient = apiClient;
        this.observer = observer;
        requestLocationUpdates();
    }

    @Override
    protected void onUnsubscribed(GoogleApiClient apiClient) {
        removeLocationUpdates();
        this.listener = null;
        this.observer = null;
        this.apiClient = null;
    }

    private void requestLocationUpdates() {
        synchronized (wasGoogleClientReady) {
            wasGoogleClientReady.set(true);
            listener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    observer.onNext(location);
                }
            };
            LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, listener);
        }
    }

    private void removeLocationUpdates() {
        if (apiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, listener);
        }
    }

    private void reconfigureLocationUpdates(LocationRequest locationRequest) {
        synchronized (wasGoogleClientReady) {
            this.locationRequest = locationRequest;
            if (wasGoogleClientReady.get()) {
                removeLocationUpdates();
                requestLocationUpdates();
            }
        }
    }

    public static class LocationUpdateReconfigurableObservable extends Observable<Location> {

        private final LocationUpdatesObservable locationUpdatesObservable;

        public LocationUpdateReconfigurableObservable(LocationUpdatesObservable locationUpdatesObservable) {
            super(RxJavaHooks.onCreate(locationUpdatesObservable));
            this.locationUpdatesObservable = locationUpdatesObservable;
        }

        public void reconfigure(LocationRequest request) {
            locationUpdatesObservable.reconfigureLocationUpdates(request);
        }

    }

}

@mcharmas
Copy link
Owner

I think laveraging what RxJava has to offer is better idea. For example flatmapping some kind of Observable<LocationRequest> to location updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants