package io.nlopez.smartlocation.rx; import android.content.Context; import android.location.Address; import android.location.Location; import com.google.android.gms.location.DetectedActivity; import java.util.List; import io.nlopez.smartlocation.OnActivityUpdatedListener; import io.nlopez.smartlocation.OnGeocodingListener; import io.nlopez.smartlocation.OnGeofencingTransitionListener; import io.nlopez.smartlocation.OnLocationUpdatedListener; import io.nlopez.smartlocation.OnReverseGeocodingListener; import io.nlopez.smartlocation.SmartLocation; import io.nlopez.smartlocation.geocoding.utils.LocationAddress; import io.nlopez.smartlocation.geofencing.utils.TransitionGeofence; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.Single; import io.reactivex.SingleEmitter; import io.reactivex.SingleOnSubscribe; import io.reactivex.functions.Action; import io.reactivex.subjects.SingleSubject; /** * Creates RxJava Observables for all the library calls. * <p/> * For now it provides just basic support for all the available actions. */ public class ObservableFactory { private ObservableFactory() { throw new AssertionError("This should not be instantiated"); } /** * Returns a RxJava Observable for Location changes * * @param locationControl instance with the needed configuration * @return Observable for Location changes */ public static Observable<Location> from(final SmartLocation.LocationControl locationControl) { return Observable.create(new ObservableOnSubscribe<Location>() { @Override public void subscribe(final ObservableEmitter<Location> emitter) throws Exception { locationControl.start(new OnLocationUpdatedListener() { @Override public void onLocationUpdated(Location location) { emitter.onNext(location); } }); } }).doOnDispose(new Action() { @Override public void run() throws Exception { locationControl.stop(); } }); } /** * Returns a RxJava Observable for Activity Recognition changes * * @param activityControl instance with the needed configuration * @return Observable for Activity changes */ public static Observable<DetectedActivity> from(final SmartLocation.ActivityRecognitionControl activityControl) { return Observable.create(new ObservableOnSubscribe<DetectedActivity>() { @Override public void subscribe(final ObservableEmitter<DetectedActivity> emitter) throws Exception { activityControl.start(new OnActivityUpdatedListener() { @Override public void onActivityUpdated(DetectedActivity detectedActivity) { emitter.onNext(detectedActivity); } }); } }).doOnDispose(new Action() { @Override public void run() { activityControl.stop(); } }); } /** * Returns a RxJava Observable for Geofence transitions * * @param geofencingControl instance with the needed configuration * @return Observable for Geofence transitions (enter, exit, dwell) */ public static Observable<TransitionGeofence> from(final SmartLocation.GeofencingControl geofencingControl) { return Observable.create(new ObservableOnSubscribe<TransitionGeofence>() { @Override public void subscribe(final ObservableEmitter<TransitionGeofence> emitter) { geofencingControl.start(new OnGeofencingTransitionListener() { @Override public void onGeofenceTransition(TransitionGeofence transitionGeofence) { emitter.onNext(transitionGeofence); } }); } }).doOnDispose(new Action() { @Override public void run() { geofencingControl.stop(); } }); } /** * Returns a RxJava single for direct geocoding results, aka get a Location from an address or name of a place. * * @param context caller context * @param address address or name of the place we want to get the location of * @param maxResults max number of coincidences to return * @return Single for results. Gets a terminal event after the response. */ public static Single<List<LocationAddress>> fromAddress(final Context context, final String address, final int maxResults) { return SingleSubject.create(new SingleOnSubscribe<List<LocationAddress>>() { @Override public void subscribe(final SingleEmitter<List<LocationAddress>> emitter) { SmartLocation.with(context).geocoding().add(address, maxResults).start(new OnGeocodingListener() { @Override public void onLocationResolved(String name, List<LocationAddress> results) { emitter.onSuccess(results); } }); } }); } /** * Returns a RxJava single for reverse geocoding results, aka get an address from a Location. * * @param context caller context * @param location location we want to know the address od * @param maxResults max number of coincidences to return * @return Single for results. Gets a terminal event after the response */ public static Single<List<Address>> fromLocation(final Context context, final Location location, final int maxResults) { return SingleSubject.create(new SingleOnSubscribe<List<Address>>() { @Override public void subscribe(final SingleEmitter<List<Address>> emitter) { SmartLocation.with(context).geocoding().add(location, maxResults).start(new OnReverseGeocodingListener() { @Override public void onAddressResolved(Location original, List<Address> results) { emitter.onSuccess(results); } }); } }); } }