Java (19.09)


Java SDK shares a common core with an alternative Android SDK.

Process of setting up Countly Java SDK includes 2 simple steps: adding SDK as dependency to your project and initializing SDK. Once those are done, you'll have basic analytics on your server like users, sessions, devices, etc.

Adding SDK as a dependency

SDK is hosted on MavenCentral, more info can be found here and here. To add it, you first have to add the MavenCentral repository. For gradle you would do it something like this:

buildscript {
repositories {

The dependency can be added as:

dependencies {
implementation "ly.count.sdk:java:19.09-sdk2-rc"

Or as:


Initializing the Java SDK

To start Countly SDK, you need to create a config class and pass it to the init method. To that method you also pass the path where countly can store it's things.

Config config = new Config("http://YOUR.SERVER.COM", "YOUR_APP_KEY")
                .enableFeatures(Config.Feature.Events, Config.Feature.Sessions, Config.Feature.CrashReporting, Config.Feature.UserProfiles)
File targetFolder = new File("d:\\__COUNTLY\\java_test\\");                
Countly.init(targetFolder, config);

In our Config instance we:

  • Told SDK not to use https (note http:// in url) and to send data to Countly server located at http://YOUR.SERVER.COM. We also specified app key (YOUR_APP_KEY).
  • Enabled test mode (read - crash whenever in inconsistent state, don't forget to disable it in Production!).
  • Set logging level to DEBUG to make sure everything works as expected.
  • Enabled crash reporting feature and tell SDK to use UUID strategy, that is random UUID string, as device id.

Recording first event

Now let's record our first event:


Countly will record an event with a key purchase-btn with sum of 10 and will eventually send it to our Countly server with next request. You can also add segmentation, count and duration to an event.

Modifying user profile

To set standard properties, call respective methods of UserEditor:

        .setName("Firstname Lastname")

To set custom properties, call set(). To send modification operations, call corresponding method:

        .set("mostFavoritePet", "dog")
        .inc("phoneCalls", 1)
        .pushUnique("tags", "fan")
        .pushUnique("skill", "singer")


Countly SDK stores serialized versions of following classes: InternalConfig, SessionImpl, RequestImpl, CrashImpl, UserImpl & TimedEvents. All those are stored in device memory, in binary form, in separate files with filenames prefixed with [CLY]_.

Test mode

To ensure correct SDK behaviour, please use Config.enableTestMode() when you app is in development and testing. In test mode Countly SDK raises RuntimeExceptions whenever is in inconsistent state. Once you remove Config.enableTestMode() call from your initialization sequence, SDK stops raising any Exceptions and switches to logging errors instead (if logging wasn't specifically turned off). Without having test mode on during development you may encounter some important issues with data consistency in production.


With no special steps performed, SDK will count any new app install (see note above regarding device ID persistence) as new user. In some cases, like when you have some kind of authentication system in your app, that's not what you want. When actual person should be counted as one user in Countly irrespective of number of app installs this user has and when you can provide user id to Countly SDK, you should use login calls.


Session in Countly is a single app launch or several app launches if time between them is less than 30 seconds (by default). Of course you can override this behaviour.

Session lifecycle methods include:

  • session.begin() must be called when you want to send begin session request to the server. This request contains all device metrics: device, model, carrier, etc.
  • session.update() can be called to send a session duration update to the server along with any events, user properties and any other data types supported by Countly SDK. Called each Config.sendUpdateEachSeconds seconds in auto session mode.
  • session.end() must be called to mark end of session. All the data recorded since last session.update() or since session.begin() in case no updates have been sent yet, is sent in this request as well.


Events in Countly represent some meaningful event user performed in your application within a Session. Please avoid recording everything like all taps or clicks user performed. In case you do, it will be very hard to extract valuable information from generated analytics.

An Event object contains following data types:

  • name, or event key. Required. Unique string which identifies the event.
  • count - number of times. Required, 1 by default. Like number of goods added to shopping basket.
  • sum - sum of something, amount. Optional. Like total sum of the basket.
  • dur - duration of the event. Optional. For example how much time user spent to checking out.
  • segmentation - some data associated with the event. Optional. It's a Map<String, String> which can be filled with arbitary data like {"category": "Pants", "size": "M"}.

Standard way of recording events is through your Session instance:

                    .addSegments("category", "pants", "size", "M")

Please note last method in that call chain, .record() call is required for event to be recorded.

Example above results in new event being recorded in current session. Event won't be sent to the server right away. Instead, Countly SDK will wait until one of following happens:

  • Config.sendUpdateEachSeconds seconds passed since begin or last update request in case of automatic session control.
  • Config.eventsBufferSize events have been already recorded and not sent yet.
  • Session.update() have been called by developer.
  • Session.end() have been called by developer or by Countly SDK in case of automatic session control.

Timed events

There is also special type of Event supported by Countly - timed events. Timed events help you to track long continuous interactions when keeping an Event instance is not very convenient.

Basic use case for timed events is following:

  • User starts playing a level "37" of your game, you call Countly.session().timedEvent("LevelTime").addSegment("level", "37") to start tracking how much time user spends on this level.
  • Then something happens when user is in that level, for example user bought some coins. Along with regular "Purchase" event, you decide you want to segment "LevelTime" event with purchase information: Countly.session().timedEvent("LevelTime").setSum(9.99).
  • Once user stopped playing, you need to stop recording this event: Countly.session().timedEvent("LevelTime").endAndRecord()

Once this event is sent to the server, you'll see:

  • how much time users spend on each level (duration per level segmentation);
  • which levels are generating most revenue (sum per level segmentation);
  • which levels are not generating revenue at all since you don't show ad there (0 sum in level segmentation).

With timed events, there is one thing to keep in mind: you have to end timed event for it to be recorded. Without endAndRecord() call, nothing will happen.



Please sign in to leave a comment.