Skip to content

cursorinsight/ci-trap-android

Repository files navigation

Trap Library for Android

This library can collect various device and user data, forwarding it to a specified endpoint. The following data collectors are bundled with this version:

  • Accelerometer
  • Gravity
  • Gyroscope
  • Magnetometer
  • Bluetooth LE devices connected / peered (Needs interactive permission, namely precise location)
  • Approximate and precise location (Needs interactive permission)
  • WiFi connection and available networks (Needs interactive permissions, namely precise location)
  • Touch
  • Indirect pointer (mouse)
  • Pencil and stylus
  • Tap gesture
  • Battery status
  • Device specific metadata

How to use it

Option A - Using a custom Application implementation

You can check out the Example app in this project for a working example. The application needs to either use the provided TrapApplication as the android:name value for the <application> tag in the AndroidManifest.xml, or subclass TrapApplication if you also need to use a custom Application class. Configuration is done via a <meta-data> tag within the <application> tag.

1. Specify the application class

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:name="com.cursorinsight.trap.TrapApplication"
    >
        <activity
            android:name=".MainActivity"
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2. (Optional) Use a custom config class

Create the configuration provider implementation.

package com.example.application

import android.app.Application
import java.io.File
import java.net.URI
import java.util.UUID

@Suppress("unused")
class MyConfig: TrapConfigProvider {
    override fun getConfig(application: Application): TrapConfig {
        val config = TrapConfig()

        // Can be a websocket or http server
        config.reporter.url = "https://my.server.com"
        
        // Use a special set of data collectors
        config.collectors = mutableListOf(TrapCoarseLocationCollector())

        // Set session id
        config.initSessionId(application)

        return config
    }
}

Specify your configuration provider in the AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:name="com.cursorinsight.trap.TrapApplication"
    >
        <meta-data android:name="trap:config" android:value="com.cursorinsight.trap.MyConfig" />

        <activity
            android:name=".MainActivity"
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Option B - Intialize TrapManager from code

Execute the following code during application startup. Preferably in the onCreate method of the Application, by subclassing the default Android Application implementation. An alternative option can be to execute the code in the onCreate method of the main activity of the application, before ˛ calling super.onCreate().

val config = TrapConfig()
config.reporter.url = "https://example.com/api/post/{streamId}/{sessionId}"

// Use a special set of data collectors
config.collectors = mutableListOf(TrapCoarseLocationCollector())

// Set session id
config.initSessionId(application)

// Instantiate the TrapManager
trapManager = TrapManager.getInstance(application, config)

Providing custom metadata

You can add and remove custom metadata (a string key-value pair), that will be sent to the server periodically as part of the metadata event.

Adding metadata:

trapManager.addCustomMetadata("some-key", "some-value")

Removing metadata:

trapManager.removeCustomMetadata("some-key")

Sending event with custom data

You can add a custom event to the event stream as well. This can contain any JSON serizable data. It will be sent to the server only once, after it is added to the stream.

trapManager.addCustomEvent(with(JSONObject()) {
    put("some-key", "some-data")
    put("numeric-data-key", 2)
    put("boolean-data-key", false)
    this
})

Ask for interactive permissions (if not previously requested) - in both cases

if (!TrapBluetoothCollector.checkPermissions(activity)) {
    TrapBluetoothCollector.requirePermissions(activity) {
    }
}
if (!TrapWiFiCollector.checkPermissions(activity)) {
    TrapWiFiCollector.requirePermissions(activity) {
    }
}
if (!TrapPreciseLocationCollector.checkPermissions(activity)) {
    TrapPreciseLocationCollector.requirePermissions(activity) {
    }
}

Note: See the MainActivity.kt from the example project for a full example.

Documentation

Generate documentation from the source comments:

./gradlew dokkaHtml

After which you can find the generated documentation in build/dokka

Dependencies

This library depends on the following 3rd party libraries:

For documentation generation:

Legal Warning

Many of the data types collected by this library is capable of identifying the individual user, therefore the integrating app can be affected by GDPR and/or CCPA. You are solely responsible for the data collected and processed via this library.

License

Licensed under the MIT license.