Esri's Geotrigger Service is replacing Geoloqi! Learn More | FAQ

Getting Started with the Android SDK

This is the source code for the Geoloqi Android SDK. The SDK provides real-time location tracking, messaging, geofencing, storage and analytics tools for developers working on location based apps.

To view a sample implementation of the Geoloqi Android SDK you can check out the public Geoloqi-Android-SDK project on GitHub.

For more information, visit: developers.geoloqi.com

Installation

The Geoloqi Android SDK is distributed as a JAR library. Simply drop the .jar into your project's libs/ directory and you should be good to go.

For developers with access to the Geoloqi Android SDK source code, you can also reference the SDK as an Android Library Project.

After pulling down the source you can easily reference an Android Library project from Eclipse or from the command line.

If you're having trouble try checking your application's project.properties file.

Packaging

To generate a distribution of the SDK you need to do the following:

$ cd Geoloqi-Android-SDK-Private

# Necessary only once!
$ android update project --path .

$ ant clean dist docs

The .jar file will be generated in the bin/ directory of your project. Javadoc will be generated in the bin/docs/ directory.

The dist and docs commands are simply two custom ant build targets and are declared in the project's build.xml file.

Note: The default build expects Git to be located at /usr/bin/git. You can specify an alternate path in your local.properties file (e.g. git.path=/usr/local/git/bin/git).

Usage

Before you begin, you'll need to modify your application's AndroidManifest.xml file to include the following permissions.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />

<!-- Note: This custom permission name should begin with your application's package name! -->
<permission
    android:name="com.geoloqi.android.sample.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<!-- These permissions are required to enable the C2DM features of the SDK. -->
<uses-permission android:name="com.geoloqi.android.sample.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

Optionally, you may also want to include the ACCESS_MOCK_LOCATION permission if you plan on doing any testing.

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />

To enable the tracker you'll need to declare the tracking service and (optionally) the push messaging receiver.

<application>
    <service
        android:name="com.geoloqi.android.sdk.service.LQService"
        android:exported="false" />
    <receiver
        android:name="com.geoloqi.android.sdk.receiver.LQDeviceMessagingReceiver"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <!-- This should equal your application's package name! -->
            <category android:name="com.geoloqi.android.sample" />
        </intent-filter>
    </receiver>
</application>

Credentials

Before starting the service you need to provide your app credentials. The preferred method is to create a geoloqi.properties file in your application's /assets directory. The properties file should follow the format below:

# Your Geoloqi API Key (required)
client_id=YOUR_API_KEY

# Your Geoloqi API Secret (not recommended, you shouldn't need to set this)
client_secret=

# Your GCM sender ID. This is required for push
# messaging to work!
gcm_sender_id=0000000001

# The name of the drawable to be displayed with incoming push
# notifications. The image must be located in one of your
# res/drawable folders. Do not include the file extension here.
# The SDK must be able to find a valid status bar icon or push
# messages will fail!
push_icon=ic_stat_notify

If for some reason you cannot provide a properties file, you can also set your client credentials manually:

LQSharedPreferences.setClientId("YOUR_API_KEY");
LQSharedPreferences.setClientSecret(""); // Don't set this! Provide a blank string.
LQSharedPreferences.setGcmPushAccount("4815162342");
LQSharedPreferences.setPushIcon("ic_stat_notify");

Note: Make sure you set these values before starting the service!

Starting the Service

The easiest way to get started is to spin up the tracking service when the user takes some action (such as launching your app). You can start the Geoloqi tracker like starting any other Android Service.

// Start the tracking service
Intent intent = new Intent(this, LQService.class);
startService(intent);

This code will start the background service, create an anonymous user account and start requesting location updates from the system. It's that easy!

Events

If you want to be notified when certain events occur, such as the logging of a new location fix or the triggering of a nearby geofence, you should extend the abstract class LQBroadcastReceiver, which is an implementation of BroadcastReceiver.

There are several ways to do this, the quickest is to dynamically register the receiver as an anonymous inner class in one of your application's Activity classes.

@Override
public void onResume() {
    super.onResume();

    // Define what BroadcastIntent actions your receiver will
    // listen for. In this case we are registering to receive only
    // broadcast intents with the ACTION_LOCATION_CHANGED action.
    final IntentFilter filter = new IntentFilter();
    filter.addAction(LQBroadcastReceiver.ACTION_LOCATION_CHANGED);

    // Register our broadcast receiver with the IntentFilter
    // created above.
    registerReceiver(new LQBroadcastReceiver() {
        @Override
        public void onLocationChanged(Context context, Location location) {
            // Let your imagination run wild here...
        }
    }, filter);
}

Note that you may want to unregister the receiver in your activity's onPause method. In that case it may be easier to bind the receiver to a private property on the Activity.

private LQBroadcastReceiver mLocationReceiver = new LQBroadcastReceiver() {
    @Override
    public void onLocationChanged(Context context, Location location) {
        // Let your imagination run wild here...
    }
};

@Override
public void onResume() {
    super.onResume();

    // Register our broadcast receiver
    registerReceiver(mLocationReceiver, filter);
}

@Override
public void onPause() {
    super.onPause();

    // Unregister our broadcast receiver
    unregisterReceiver(mLocationReceiver);
}

In either case, your Activity will be notified only when it has focus and is in the foreground. If you would like to intercept broadcast intents from the location tracker at any point, even when your application is not in the foreground, you should register the broadcast receiver from your application's manifest file.

<application>
    <receiver
        android:name=".receiver.SampleReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="com.geoloqi.android.sdk.action.LOCATION_CHANGED" />
        </intent-filter>
    </receiver>
</application>

In this case you provide an implementation of LQBroadcastReceiver named SampleReceiver in the receiver package. The actions you would like your receiver to be sent are listed in the <intent-filter>...</intent-filter> section just like the previous example.

This will ensure your broadcast receiver will always be notified, even if your application is not currently running. This allows you a great deal of flexibility and provides you with the opportunity to do everything from creating a Notification to launching a new Activity.

If you would like to create a dual-purpose broadcast receiver, this is a good pattern to follow.

@Override
public void onLocationChanged(Context context, Location location) {
    try {
        OnLocationChangedListener listener = (OnLocationChangedListener) context;
        listener.onLocationChanged(location);
    } catch (ClassCastException e) {
        // The broadcast receiver is running with a Context that
        // does not implement OnLocationChangedListener. If your activity
        // has implemented the interface, then this generally means
        // that the receiver is running in a global context and
        // is not bound to any particular activity.
    }
}

public interface OnLocationChangedListener {
    public void onLocationChanged(Location location);
}

From here you can register the receiver in your activities and implement any of the public interfaces you've defined on the receiver. The interface methods will then be called if the activity is in the foreground when the receiver gets a new broadcast.

Service Binding

Warning, here be dragons! If you are an advanced user, you can bind to the tracking service from your Activity and call any public methods. This may be useful if you want to trigger API calls from your application's UI.

Local service binding can be easily achieved, but with great power comes great responsibility.

@Override
public void onResume() {
    super.onResume();

    // Bind to the tracking service so we can call public methods on it
    Intent intent = new Intent(this, LQService.class);
    bindService(intent, mConnection, 0);
}

@Override
public void onPause() {
    super.onPause();

    // Unbind from LQService
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
}

private LQService mService;
private boolean mBound;

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        try {
            // We've bound to LocalService, cast the IBinder and get LocalService instance.
            LQBinder binder = (LQBinder) service;
            mService = binder.getService();
            mBound = true;
        } catch (ClassCastException e) {
            // Pass
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mBound = false;
    }
};

Once the Service binding has completed you can call methods from the service instance like mService.getTracker() or mService.getSession(). These two objects are the backbone of the Geoloqi SDK and expose many useful methods.

Note that you should always make sure you start the tracking service explicitly before attempting to bind to it. If you bind to the tracking service using the BIND_AUTO_CREATE flag the service may not continue to function once your Activity has stopped.

Calling API Methods

Binding to the tracking service also allows you to call Geoloqi API methods directly. After following the directions above, simply get an instance of the session.

// Performing a basic GET request
if (mService != null) {
    LQSession session = mService.getSession();

    // Send the request
    session.runGetRequest("account/profile", new OnRunApiRequestListener() {
        @Override
        public void onSuccess(LQSession session, HttpResponse response) {
            // Consume the response!
            // ...
        }
        @Override
        public void onFailure(LQSession session, LQException e) {
            Log.e(TAG, e.getMessage());
        }
        @Override
        public void onComplete(LQSession session, HttpResponse response, StatusLine status) {
            // The server did not return a 200-OK response!
            // ...
        }
    });
}

// Performing a basic POST request
if (mService != null) {
    LQSession session = mService.getSession();

    // Build your request
    JSONObject geonote = new JSONObject();
    try {
        geonote.put("text", "Don't forget the milk!");
        geonote.put("latitude", 45.5037078163837);
        geonote.put("longitude", -122.622699737549);
        geonote.put("radius", 467);
        geonote.put("place_name", "Grocery Store");
    } catch (JSONException e) {
        // Pass
    }

    // Send the request
    session.runPostRequest("geonote/create", geonote, new OnRunAPIRequestListener() {
        @Override
        public void onSuccess(LQSession session, HttpResponse response) {
            // Consume the response!
            // ...
        }
        @Override
        public void onFailure(LQSession session, LQException e) {
            Log.e(TAG, e.getMessage());
        }
        @Override
        public void onComplete(LQSession session, HttpResponse response, StatusLine status) {
            // The server did not return a 200-OK response!
            // ...
        }
    });
}

The API request is run asynchronously on a background Thread. Simply provide a callback listener to receive the response and you're done! The session instance automagically signs the request with the credentials of the currently authenticated user (or with your application's client ID).

Contributing

Contributors should follow the Android Code Style Guidelines for Contributors where appropriate.

License

Copyright 2011 by Geoloqi.com and contributors.

See LICENSE