Android SDK

The Android SDK is hosted at bintray. You can see the complete javadoc here.

Install

There is 2 steps to the installation.

Add reposity

In you project-level build.gradle, make sure jcenter is added:

allprojects {
    repositories {
                jcenter() // this should already be here on new projects
    }
}

Add dependency

In your module-level build.gradle, add the following lines:

compile('it.emplate:emplate:1.6.1@aar') {
    transitive = true;
}

Overview

The SDK provides the following functionality: * Interaction with the Emplate JSON API (using retrofit) * Monitoring for Beacons * Various utility methods

Interaction with the API

The SDK provides an interface with all the available actions that can be performed on models in the API. The classes are in the it.emplate.androidsdk.api package (see javadoc).

The IEmplateApi interface in the defines the possible actions. To get an instance of the API object that is configured for your client, you use the Emplate.getInstance(context) method.

Examples

Getting beacons from your organization in the API

// Get the API instance
IEmplateApi api = Emplate.getInstance(context);
Call<List<Beacon>> listCall = api.beaconsGet(null);

// Make the call on a background thread. The callback is run on the UI thread
listCall.enqueue(new Callback<List<Beacon>>() {
    @Override
    public void onResponse(Call<List<Beacon>> call, Response<List<Beacon>> response) {
        // We got a response from the server
        if (response.isSuccessful() && response.body != null) {
            // We got something from the server
            List<Beacon> beacons = response.body();

            // Do something with the response
        }
        else {
            // Something went wrong
            ResponseBody responseBody = response.errorBody();
            int statusCode = response.code(); // might be a 4XX or 5XX error
        }
    }

    @Override
    public void onFailure(Call<List<Beacon>> call, Throwable t) {
        // Something is wrong with our request, and we didn't get a response from the server
        Log.e("Error", t.getMessage());
    }
});

Attempt to log in as a Guest

// Get the credentials from the UI somehow
Guest guest = new Guest();
guest.setEmail("email@example.com");
guest.setPassword("somepassword");

// Get the API instance
IEmplateApi api = Emplate.getInstance(context);

// We pass the guest object as a parameter
api.tokensPost(guest).enqueue(new Callback<Token>() {
    @Override
    public void onResponse(Call<Token> call, Response<Token> response) {
        if (response.body() != null) {
            // The token has to be added as a header to every request
            final Token token = response.body();

            // Retrofit provides us with interceptors to facilitate this
            Emplate.addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request original = chain.request();

                    // Add the Authorization header, and preserve other headers
                    Request request = original.newBuilder()
                            .header("Authorization", "Bearer " + token.getContent())
                            .headers(original.headers()) // Preserve headers
                            .method(original.method(), original.body())
                            .build();

                    return chain.proceed(request);
                }
            });

            // Now every new call made through the Emplate API instance will be as the Guest
        }
        else if (response.code() == 401) {
            // The user didn't provide a valid email+password, handle it from here
        }
    }

    @Override
    public void onFailure(Call<Token> call, Throwable t) {}
});

Once the interceptor has been added, every subsequent request will automatically add the header to the request, and “act” as the logged in Guest. You can read more about interceptors in the retrofit documentation.

Monitoring for Beacons

The it.emplate.androidsdk.monitoring package provides the interfaces and classes that allow you to interact and monitor nearby beacons.

Before you start monitoring for beacons, ensure that the following steps are completed: 1. Ensure you have the proper permissions:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

From Android M and forward, you must ask for Manifest.permission.ACCESS_COARSE_LOCATION on runtime in order to monitor for beacons.

  1. Ensure that bluetooth and location is turned on by the user.

Now you can start the service java Intent beaconMonitor = new Intent(this, BeaconMonitorService.class); bindService(beaconMonitor, monitorServiceConnection, Context.BIND_AUTO_CREATE); The service connection allows you to interact with the service once you’ve established a connection.

A sample config might look like so: ```java /** * The service connection is used to handle interaction with the {@link BeaconMonitorService}. * This allows us to register multiple listeners, setup our configuration, and clean up * after we disconnect from the service (or get disconnected). */ private ServiceConnection monitorServiceConnection = new ServiceConnection() { /** * We have connected to the BeaconMonitorService * @param name * @param service */ @Override public void onServiceConnected(ComponentName name, IBinder service) { beaconBinder = (BeaconMonitorService.BeaconBinder) service;

    // Register our configuration with Emplate SDK
    beaconBinder.registerConfigurationListener(proximityConfig);
    
    // IMPORTANT: Register a listener of beacon events
    beaconBinder.registerBeaconListener(beaconListener);

    statusText.setText("Connected to Service, scanning for beacons");
}

@Override
public void onServiceDisconnected(ComponentName name) {
    // Be sure to remove our listener to avoid memory leaks
    beaconBinder.clearListener(beaconListener);
    statusText.setText("Disconnected from service");
} }; ```

The configuration listener is called once the BeaconMonitoringService is ready to configure how often to scan for beacons:

private ProximityConfigurationListener proximityConfig = new ProximityConfigurationListener() {
@Override
public void configureProximityManager(ProximityManager proximityManager) {
    proximityManager.configuration()
    // Balanced power usage
    .scanMode(ScanMode.BALANCED)
    
    // Active scan for 5 seconds, then pause for 4 seconds
    .scanPeriod(ScanPeriod.create(TimeUnit.SECONDS.toMillis(5), TimeUnit.SECONDS.toMillis(4)))
    
    // We wait maximum of 30 seconds before regarding a beacon as inactive, checking every 4 seconds
    .activityCheckConfiguration(ActivityCheckConfiguration.create(TimeUnit.SECONDS.toMillis(30),
            TimeUnit.SECONDS.toMillis(4)))
    
    // Some devices need this to continually scan for beacons
    .forceScanConfiguration(new ForceScanConfiguration(TimeUnit.SECONDS.toMillis(8),
            TimeUnit.SECONDS.toMillis(2)))
    
    // If using OnBeaconsUpdated, make sure we don't get called too often
    .deviceUpdateCallbackInterval(TimeUnit.SECONDS.toMillis(5))
    
    // We use a limited mean value of 3 to ensure that our ranging is somewhat stable
    .rssiCalculator(RssiCalculators.newLimitedMeanRssiCalculator(3))
    
    // Enable this to automatically send battery life to the API
    .monitoringEnabled(false)
    
    // How often should this be done?
    .monitoringSyncInterval(60);
}
};

The line beaconBinder.registerBeaconListener(beaconListener); tells the service which object to call when it finds beacons. This is called on the UI thread for you to update your UI based on the beacons.

There are 2 different interfaces to use, depending on your use case: 1. If you just want to get notifications when the phone find a new beacon (or looses a beacon of sight), use BeaconMonitorListener 2. If you want to get continuous updates about the beacons near you, use BeaconListener

It is possible to register multiple listeners using beaconBinder.registerBeaconListener(beaconListener);. Remember to clear your listeners (beaconBinder.clearListener(listener)) when you don’t need to listen for updates anymore. Otherwise the service will keep a reference to the object after you are done using it, causing memory leaks.