Skip to content

Instantly share code, notes, and snippets.

@beaucollins
Created October 2, 2015 19:52
Show Gist options
  • Select an option

  • Save beaucollins/05d32b40f87233a47e92 to your computer and use it in GitHub Desktop.

Select an option

Save beaucollins/05d32b40f87233a47e92 to your computer and use it in GitHub Desktop.
package com.automattic.geopit;
import android.app.Activity;
import android.app.Application;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.automattic.geopit.api.GeopitService;
import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;
import javax.inject.Inject;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class RangingService extends Service {
protected static final String TAG = "RangingService";
private static final Region REGION = new Region("region", null, null, null);
private static final String STARTED_FROM_APP_EXTRA = "started_in_app";
@Inject public BeaconManager beaconManager;
protected GeopitService service = GeopitService.Client.createService();
protected CheckinThrottle throttle = new CheckinThrottle();
protected DisplayIntentBuilder displayIntentBuilder;
protected CheckinBroadcaster checkinBroadcaster;
protected CheckinNotificationBuilder checkinNotificationBuilder;
protected NotificationDisplay notificationDisplay;
private int startCount = 0;
public RangingService() {
}
@Override
public void onCreate() {
super.onCreate();
Injector.obtain(getApplicationContext()).inject(this);
getApplication().registerActivityLifecycleCallbacks(lifecycleObserver);
displayIntentBuilder = new DisplayIntentBuilder(this);
checkinBroadcaster = new CheckinBroadcaster(this);
checkinNotificationBuilder = new CheckinNotificationBuilder(this);
notificationDisplay = new NotificationDisplay(this);
beaconManager.setRangingListener((region, list) -> {
if (list.size() <= 0) return;
Beacon nearest = list.get(0);
if (nearest == null) return;
checkin(nearest);
});
if (BuildConfig.DEBUG) {
Log.d(TAG, "Start ranging");
}
beaconManager.connect(() -> {
try {
beaconManager.startRanging(REGION);
} catch (RemoteException e) {
Log.d(TAG, "Failed to start ranging ", e);
}
});
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (BuildConfig.DEBUG) Log.d(TAG, "Received start " + startId + ": " + intent);
if (intent.getBooleanExtra(STARTED_FROM_APP_EXTRA, false)) {
startCount += 1;
}
// TODO: Determine if we were started from the app or from being booted
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
if (BuildConfig.DEBUG)
Log.d(TAG, "Killing ranging service");
try {
beaconManager.stopRanging(REGION);
} catch (RemoteException e) {
Log.e(TAG, "stopRanging failed", e);
}
beaconManager.disconnect();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not implemented");
}
void checkin(Beacon beacon) {
final Context context = getApplicationContext();
// Attempt to request a checkin
Observable.just(beacon)
.skipWhile(throttle)
.flatMap(b -> service.checkin(Geopit.getDeviceId(context), b.getProximityUUID()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onCheckin, error -> Log.d(TAG, "Failed to check in", error));
}
private void onCheckin(GeopitService.CheckinStatus checkinStatus) {
// Broadcasts an Intent via LocalBroadcastManager for the app to respond to while open
Observable.just(checkinStatus)
.map(displayIntentBuilder)
.subscribe(checkinBroadcaster);
if (BuildConfig.DEBUG) {
Log.d(TAG, "Checkin with action: " + checkinStatus.checkin.action);
Log.d(TAG, "Activity count: " + startCount);
}
// Builds and displays a notification
Observable.just(checkinStatus)
.filter(status -> startCount <= 0)
.filter(status -> status.checkin.action != null)
.map(checkinNotificationBuilder)
.subscribe(notificationDisplay);
}
private Application.ActivityLifecycleCallbacks lifecycleObserver = new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
// started
startCount += 1;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
startCount -= 1;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment