-
Notifications
You must be signed in to change notification settings - Fork 207
Writing Integrations
We're huge fans of open-source, and we absolutely love getting good contributions to analytics-android! Integrations are available to thousands of Segment customers and we have hundreds of integrations already in our queue, so it's important that you do the following before writing a new integration.
Agree to the Segment Platform Partners Agreement which is necessary to make contributions to Segment Integrations.
Apply to be a Segment partner: https://segment.com/partners/.
Android integrations are written as Android Libraries. If you have your own SDK, this would be the same.
Since the integrations are decoupled from our library, you are free to use whatever IDE, build system, folder structure you wish. The only requirement is that integrations be uploaded to Maven Central or jCenter to make it easier for mutual customers to add your integration.
You can see an example for the Mixpanel android integration. Feel free to clone the repository, and replace references to Mixpanel with your own SDK.
To access the Segment Packaged API, you’ll need to declare a dependency on our library.
provided 'com.segment.analytics.android:analytics:4.0.0-SNAPSHOT'
We’ll notify partners when there are changes to our integration API. We won’t make any incompatible changes, but we may add new features.
For testing your integration, we also have a few utility classes in the test artifact.
testCompile 'com.segment.analytics.android:analytics-tests:4.0.0-SNAPSHOT'
// Note: while this is in beta, the package API will be released as a snapshot, so you’ll need to add the snapshot repository.
repositories {
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
There are three important classes when it comes to writing an integration.
- The
Analyticsclass - The
Integrationclass - The
Integration.Factoryclass
The Analytics class is our public facing API for customers. For integrations, it contains a few key things:
- The application
Contextobject - A
Loggerimplementation that can be specifically used by your integration.
The Logger is where you should log all transformations made by our SDK (in verbose mode), so that users can clearly see what’s going on under the covers.
The Integration.Factory class is a class that lets the Segment SDK create an object of your Integration class.
interface Integration.Factory {
// Attempts to create an integration with {@code settings}.
Integration<?> create(ValueMap settings, Analytics analytics);
// Return the key for which this factory can create an integration.
String key();
}All integrations extend from an abstract class called Integration.
public abstract class Integration<T> {
// These are the same as http://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html.
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
public void onActivityStarted(Activity activity) {
}
public void onActivityResumed(Activity activity) {
}
public void onActivityPaused(Activity activity) {
}
public void onActivityStopped(Activity activity) {
}
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public void onActivityDestroyed(Activity activity) {
}
// These are messages in the format of the Segment API.
// You can refer to the Javadocs for each payload in more detail.
// Semantically, they are the same as documented in our spec:
// https://segment.com/docs/spec/.
public void identify(IdentifyPayload identify) {
}
public void group(GroupPayload group) {
}
public void track(TrackPayload track) {
}
public void alias(AliasPayload alias) {
}
public void screen(ScreenPayload screen) {
}
// These methods are specific to client side libraries.
// Flush is when you should try to upload queued events to your server.
public void flush() {
}
// Reset is when you clear out any local user data.
public void reset() {
}
// This should return the same object your users would have to use if
// they were to integrate natively.
// e.g. Localytics would return `null`, but Mixpanel would return an instance
// of a MixpanelAPI object.
public T getUnderlyingInstance() {
return null;
}
}Our SDK calls methods on these integrations with whatever data our users have provided. You should override the methods you are interested in.
For example, here’s an SDK that only cares about the identify method.
public class ExampleIntegration extends Integration {
public static final Integration.Factory FACTORY = new Integration.Factory() {
@Override
Integration<?> create(ValueMap settings, Analytics analytics) {
String apiKey = settings.getString("apiKey");
Context context = analytics.getApplication();
return new ExampleIntegration(apiKey, context);
}
@Override
String key() {
return "example"
}
};
@Override public void identify(IdentifyPayload identify) {
ExampleSDK.identify(identify.userId(), identify.traits);
}
}For a user, the way they install your library is by declaring a dependency on your integration and by registering the factory class in their builder.
compile ‘example:segment-integration:1.2.0’
Analytics.Builder builder = new Analytics.Builder(this, ANALYTICS_WRITE_KEY);
builder.use(ExampleIntegration.FACTORY);Android doesn’t have a native JSON data type. The closest is JSONObject, but there are significant limitations in using it.
We’ve written an easier implementation, called ValueMap. It’s main advantage is that it implements the java Map interface, so you can choose to work with the APIs you’re already used to.
When reading from a ValueMap, it offers a few additional conveniences to work with.
-
getString(key) -
getInt(key, default) -
getBoolean(key, default)
They handle parsing from JSON to java primitives, and falling back gracefully to your default value if one is not available.
As we mentioned, there aren’t too many hard and fast rules, integrations are very flexible. Similarly, there aren’t any rules for naming classes, but we have a few recommendations.
- Name your integration class
{YOUR_SERVICE}Integration.java; e.g.MixpanelIntegration.javaorFlurryIntegration.java. - Expose a
public static finalfield for your Factory class. - Follow the structure in the sample repo.
By following these recommendations, you’ll make it easier for both customers to pull in your integration, and for you to update your integration. We have some internal tooling that will allow us to make PRs to your repositories whenever we release and update to our core SDK.
The integrations should be published to Maven Central. If you aren’t familiar with the process, the following resources should guide you: