Android Technical Reference
- SDK architecture
- Threading model
- Internal buffer capacity
- Flushing events
- Session management
- Performance and resources
- android.permission.READ_PHONE_STATE: We recommend that you declare this permission to allow the SDK to retrieve a mobile phone’s serial number. This allows the Medio Platform to accurately identify and report on unique users across all devices and Android OS versions. This permission only applies to phone devices (as opposed to Wi-Fi-only devices).
- android.permission.ACCESS_NETWORK_STATE: Declaring this permission allows the SDK to check the state of the device’s network connectivity before trying to send data to Medio. The SDK operates most efficiently with this permission so we recommend that you declare it in your manifest. With this permission, the SDK does not need to rely on Android’s underlying HTTP methods to fail when data connectivity is not available. This permission also allows the SDK to collection information about the data network type (e.g., mobile versus Wi-Fi) and whether the user is roaming.
- android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION: One of these permissions is required if you choose to enable the SDK’s location tracking feature. Choose coarse or fine location depending on how accurate you would like the reported location to be.
When your application calls the EventAPI.logEvent method, the SDK creates an Event object. The SDK sets the timestamp automatically in the Event object and also copies all application-defined event parameters into the Event object. Since writing to the SQLite Database is relatively slow, the SDK queues the Event object to a separate background thread and writes it to the database without blocking the application.
When the SDK flushes the events, it again defers the work of collecting all the Event objects to the separate background logging thread. Once the logging thread has collected the events to be sent, the SDK queues the events to another separate background thread. This HTTP thread GZIP compresses the events and HTTP posts the compressed data to the Medio Data Collection Service (DCS) REST API. The HTTP thread then waits for the HTTP response. If Medio DCS accepts the data, then the logging thread removes the events from the database. Note that separate threads are used for compression and HTTP request/response to avoid blocking database access while awaiting the HTTP response. To minimize memory consumption, the SDK may send events to the Medio DCS in several separate batches.
Internal buffer capacity
When the internal buffer capacity limit is reached, the SDK will purge or throw out a small number of the oldest events to make room for new events. This results in data loss but should only happen in extreme situations such as when events cannot be flushed to Medio due to prolonged lack of data connectivity or a misbehaving application logging too many events and disabling flushing.
Flushing events assumes that a data connection is available and relies on Android’s HTTP implementation to fail gracefully when a data connection is not available. You can make this behavior more efficient by enabling the android.permission.ACCESS_NETWORK_STATE permission.
The SDK spreads the sending of large amounts of events to the Medio DCS over several HTTP Post requests to minimize memory consumption. Once the Medio DCS successfully acknowledges receipt of the events, the SDK removes the events from the Android SQLite database. If the HTTP request fails for any reason, then the events are not removed. The SDK does not immediately retry failed requests. Events that are not sent to the Medio DCS successfully remain queued (stored persistently in non-volatile storage) and will be sent on the next flush either automatically or manually.
The SDK will ignore all other requests to flush if it is already busy with a previous request. New requests to flush will only be accepted after the previous flush has succeeded or failed.
Flushing events and application behavior
The SDK’s automatic flush behavior may not meet every application’s requirements. For example, if you find automatic flushing affecting critical application processing like game play, then you can disable it temporarily during these critical processing points using the
EventAPI.disableAutomaticFlushing method. Automatic flushing can be re-enabled again using the
EventAPI.enableAutomaticFlushing once the critical processing section is complete. Note your application can still flush events on demand using the
EventAPI.flushEvents method while automatic flushing is disabled or enabled.
In extreme cases, you may disable automatic flushing entirely for the life of your application. In this case, we recommend calling the
EventAPI.flushEvents method when you perform some other networking activity (if any). If your application does not have any networking activity, then we recommend calling
EventAPI.flushEvents during pauses in user interaction. For example, in the case of a game, you may wish to flush events in a “Game Over” screen or a “Main Menu” screen.
If you choose to flush events on demand instead of or in addition to automatic flushing, your application should not call
EventAPI.flushEvents too frequently to avoid compromising battery life. On the other hand, you also don’t want to take the risk of losing data by calling
EventAPI.flushEvents too infrequently, as old events are purged to allow for new ones when the internal buffer capacity limit is reached.
- The first time your application calls
EventAPI.openSession, the SDK will create a new session (labeled as Session_A in the diagram below).
- When your application calls
EventAPI.closeSession, the SDK may expire the current session.
- If your application calls
EventAPI.openSessionwithin 10 seconds of the last call to
EventAPI.closeSession, then the SDK will resume the previous session. This behavior means that the SDK will resume the previous session if the user accidentally exits your application and restarts it.
- Your application makes the final call to
- If your application calls
EventAPI.openSessionmore than 10 seconds after the last call to
EventAPI.closeSession, the SDK will create a new session (labeled as Session_B in the diagram below).
Performance and resources
The size of the SDK and its impact on application size is outlined below:
- SDK JAR file: 60KB
- Android APK with SDK (not including application instrumentation): +30KB
- Android application installed on device with SDK: +100KB
- Persistent storage used by SDK (not including application events): 12KB
- Maximum size of SDK SQLite Database for internal buffer: 1MB
We collected the following performance measurements on an HTC Sensation with a dual core 1.2GHz processor running Android 2.3.3.
Logging and flushing events
The average execution time of the EventAPI.logEvent call is 4.5ms based on 10 test runs of logging 1,000 events (average size 50 characters including name and key-value pairs).
The average execution time of the EventAPI.flushEvents call is 9.8ms based on 10 test runs of flushing 1,000 events (average size 50 characters including name and key-value pairs).
Average time to persist an event
The chart below displays the average execution time for persisting an Event to the database based on 10 test runs of writing 1,000 events with an average size of 50 characters including name and key-value pairs.
The SDK’s CPU utilization during a stress test averaged around 4% over a 30-minute period with auto-flush enabled. The stress test is setup to log 10 events per second and flush events to the Medio DCS after every 500 events logged. Each event is composed of the data shown below equating to an average of 58 characters. This utilization corresponds to 10 events logged per second over a 30 minute period, which is significantly higher than most application logging.
- Event name: select_next
- Key-value pair 1: page = stop_page_x
- Key-value pair 2: select_next = redirect_id_value_x
The charts below illustrate the RAM usage of the SDK during a stress test. We measured RAM usage by employing the Android community’s accepted methods: Unique Set Size (USS) and Proportional Set Size (PSS).
USS is the set of pages that are unique to a process. This is the amount of memory that is freed when the application is terminated.
PSS is the amount of memory shared with other processes, accounted in a way that the amount is divided evenly between the processes that share it. This is memory that would not be released if the process was terminated, but is indicative of the amount that the process is “contributing.”
The stress test is set up to log 10 events per second and flush events to the Medio DCS after every 500 events logged. Each event in the test was comprised of same data used in the CPU utilization test, equating to 58 characters per event.