Countly Product Analytics Android SDK

Overview

Countly Android SDK API

We're hiring: Countly is looking for Android SDK developers, full stack devs, devops and growth hackers (remote work). Click this link for job description

What is Countly?

Countly is a product analytics solution and innovation enabler that helps teams track product performance and customer journey and behavior across mobile, web, and desktop applications. Ensuring privacy by design, Countly allows you to innovate and enhance your products to provide personalized and customized customer experiences, and meet key business and revenue goals.

Track, measure, and take action - all without leaving Countly.

About

This repository includes the Countly Android SDK. It can also be used to get user insights from Android TV or Wear devices.

Need help? See Countly SDK for Android documentation at Countly Resources, or ask us on our Countly Analytics Community Slack channel.

Sample Android application

We have a comprehensive sample Android application which includes this SDK. Feel free to use this for testing purposes as you develop your application.

Android-sample-app

Security

Security is very important to us. If you discover any issue regarding security, please disclose the information responsibly by sending an email to [email protected] and not by creating a GitHub issue.

Other Github resources

This SDK needs one of the following Countly Editions to work:

For more information about Countly Enterprise Edition, see comparison of different Countly editions

There are also other Countly SDK repositories (both official and community supported) on Countly resources.

How can I help you with your efforts?

Glad you asked. We need ideas, feedback and constructive comments. All your suggestions will be taken care with utmost importance. We are on Twitter and Facebook if you would like to keep up with our fast progress!

Badges

If you like Countly, why not use one of our badges and give a link back to us, so others know about this wonderful platform?

Countly - Product Analytics

<a href="https://count.ly/f/badge" rel="nofollow"><img style="width:145px;height:60px" src="https://count.ly/badges/dark.svg" alt="Countly - Product Analytics" /></a>

Countly - Product Analytics

<a href="https://count.ly/f/badge" rel="nofollow"><img style="width:145px;height:60px" src="https://count.ly/badges/light.svg" alt="Countly - Product Analytics" /></a>

Support

For Community support, visit http://community.count.ly.

Comments
  • Global error catching in Android

    Global error catching in Android

    Global error catching in Android

    Expected Behavior

    I included Countly and it works properly, but when I do an un-catched java.lang.ArithmeticException: divide by zero

        var i = 0
        i /= 0
    

    Nothing is reported to backend

    Current Behavior

    App crashes, and nothing is reported to backend

    Expectation

    My app should report this to the backend, at least after next app start

    Steps to Reproduce (for bugs)

        var i = 0
        i /= 0
    

    Your Environment

    • Countly Android SDK version :29
    • Your Android version: P
    • Your device: Emulator
    • Countly 19.09
    opened by hannesa2 17
  • Got exception while trying to submit event data

    Got exception while trying to submit event data

    Hi, guys, I'm running Countly Opensource Server from docker, and I have this basic setup

    This is my server address private val countlyServerUrl: String = "http://192.168.1.244:32768"

    basic initialization

    Countly.sharedInstance().isLoggingEnabled = true
    Countly.sharedInstance().enableCrashReporting()
    Countly.sharedInstance().init(application.applicationContext, countlyServerUrl, countlyAppKey, null, DeviceId.Type.ADVERTISING_ID)
    Countly.sharedInstance().setLocation(getCountryCode(), getActualCity(), null, null)
    

    and i am sending a basic event Countly.sharedInstance().recordEvent("Something")

    but when i run the app from my phone and the search in the logs, give me this exception while trying to submit event data

    java.net.ProtocolException: Unexpected status line: <html>
    at com.android.okhttp.internal.http.StatusLine.<init>(StatusLine.java:38)
    at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:197)
    at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:103)
    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:677)
    at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:403)
    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:347)
    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:515)
    at ly.count.android.sdk.ConnectionProcessor.run(ConnectionProcessor.java:208)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)
    

    So, any help will be much appreciated

    opened by randyhbh 12
  • Add a way to stop the service - like stop()

    Add a way to stop the service - like stop()

    I want to stop the statistic sending as soon as the user opts out of this.

    The Java SDK has a dedicated stop() method to shut down the engine.

    The Android SDK has no such option. I tried calling onStop() which seems to signal something, but does not stop sending messages.

    I also tried calling Countly.sharedInstance().consent().removeConsentAll() after I configured config.setRequiresConsent(true), but this is not effective until the whole app is restarted.

    So I currently see no way to stop the sending of anaytics once Countly.sharedInstance().init(config) is called.

    opened by AshStefanOltmann 11
  • problem of Countly.sharedInstance().init

    problem of Countly.sharedInstance().init

    when I use Countly.sharedInstance().init() method,I found a terrible problem

    My test server is 192.168.18.19,default port is 80,so I use "http://192.168.18.19",but I tryed for three days ,no event could be send to the server.when I use "http://192.168.18.19:80",and the document is not say this clearly,so I think when there is no port ,can use 80 for default...

    opened by darkz1984 9
  • NullPointerException in ly.count.android.api.DeviceInfo.getResolution

    NullPointerException in ly.count.android.api.DeviceInfo.getResolution

    I got some NullPointerException on certain devices.

    Caused by: java.lang.NullPointerException at ly.count.android.api.DeviceInfo.getResolution(Unknown Source) at ly.count.android.api.DeviceInfo.getMetrics(Unknown Source) at ly.count.android.api.ConnectionQueue.beginSession(Unknown Source) at ly.count.android.api.Countly.onStartHelper(Unknown Source) at ly.count.android.api.Countly.onStart(Unknown Source) at br.com.verde.alarme.Alarme.onStart(Alarme.java:394) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166) at android.app.Activity.performStart(Activity.java:5285) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2058)

    image

    opened by rachelxj 7
  • Dependency injection / module architecture broke all thread safety

    Dependency injection / module architecture broke all thread safety

    Thread safety across the SDK was lost when synchronized methods from the old Countly god-object were moved into their respective modules. These methods are now synchronized with different locks (their interface, an inner class of the module), and are therefore no longer thread safe. Thread safety can be regained trivially by using the Countly instance passed to each module as the module and interface wide lock.

    eg.

    public class ModuleViews extends ModuleBase {
        @Inject Countly _cly;
    
        public class Views {
            public synchronized Countly recordView(String viewName) {
                // method contents...
            }
        }
    }
    

    should become

    public class ModuleViews extends ModuleBase {
        @Inject Countly _cly;
    
        public class Views {
            public Countly recordView(String viewName) {
                synchronized(_cly) {
                    // method contents...
                }
            }
        }
    }
    
    opened by aimkey 6
  • Allow logging of Throwables instead of just Exceptions

    Allow logging of Throwables instead of just Exceptions

    The Countly.logException(Exception) method's signature should be changed to Countly.logException(Throwable) (maybe update the name too?) to match the API used by Android's Log class: http://developer.android.com/reference/android/util/Log.html. This would make it easier to create a Log wrapper that logs the Throwable to countly before passing it on to Android's Log.

    enhancement 
    opened by garyp 6
  • too many sessions

    too many sessions

    I hosted a countly server on EC2, and I integrated client in my apk, it's just one page app, but there are 3000+ users, but it creates millions of sessions, is it wrong or can I reduce it?

    opened by rachelxj 6
  • Database Object Not Close Exception

    Database Object Not Close Exception

    When i exit and then re-enter my app, I get the following error in the stack. Do I need some Countly code when existing application? This is not mentionned in the small guide.

    02-18 15:35:18.290 6645-6654/com.devrap.app E/SQLiteDatabase﹕ close() was never explicitly called on database '/data/data/com.devrap.app/databases/countly' android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:2072) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1126) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1083) at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1170) at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:844) at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:228) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157) at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:231) at ly.count.android.api.CountlyDB.getEvents(Countly.java:596) at ly.count.android.api.EventQueue.(Countly.java:378) at ly.count.android.api.Countly.init(Countly.java:75) at com.devrap.app.analytix.AnalytixHelper.init(AnalytixHelper.java:39) at com.devrap.app.FormActivity.onCreate(FormActivity.java:208) at android.app.Activity.performCreate(Activity.java:4470) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992) at android.app.ActivityThread.access$600(ActivityThread.java:127) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4511) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:986) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:753) at dalvik.system.NativeStart.main(Native Method) 02-18 15:35:18.290 6645-6654/com.devrap.app E/System﹕ Uncaught exception thrown by finalizer 02-18 15:35:18.300 6645-6654/com.devrap.app E/System﹕ java.lang.IllegalStateException: Don't have database lock! at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2230) at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2322) at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2318) at android.util.LruCache.trimToSize(LruCache.java:197) at android.util.LruCache.evictAll(LruCache.java:285) at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2283) at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1255) at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:2043) at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:185) at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168) at java.lang.Thread.run(Thread.java:856)

    opened by spogher 6
  •  Not allowed to bind to service Intent

    Not allowed to bind to service Intent

    A small number of our users are encountering crash do to an " Not allowed to bind to service Intent" in Count.ly.

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.alamode.totalmobile/com.alamode.totalmobile.landing.FilesActivity}: java.lang.SecurityException: Not allowed to bind to service Intent { cmp=com.drippler.android.updates/.utils.openudid.OpenUDIDService } at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135) at android.app.ActivityThread.access$700(ActivityThread.java:143) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4950) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.SecurityException: Not allowed to bind to service Intent { cmp=com.drippler.android.updates/.utils.openudid.OpenUDIDService } at android.app.ContextImpl.bindService(ContextImpl.java:1326) at android.app.ContextImpl.bindService(ContextImpl.java:1300) at android.content.ContextWrapper.bindService(ContextWrapper.java:401) at org.OpenUDID.OpenUDID_manager.startService(OpenUDID_manager.java:107) at org.OpenUDID.OpenUDID_manager.sync(OpenUDID_manager.java:170) at ly.count.android.api.Countly.init(Countly.java:66) at com.alamode.totalmobile.landing.FilesActivity.onCreate(FilesActivity.java:69) at android.app.Activity.performCreate(Activity.java:5179) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074) ... 11 more

    opened by tracyboehrer 6
  • Simplify UDID/Device ID retrival

    Simplify UDID/Device ID retrival

    I tested that OpenUDID_manager.getOpenUDID() returns the same device id as the standard way to get device id:

    import android.provider.Settings;
    Settings.Secure.getString(ctx.getContentResolver(), Settings.Secure.ANDROID_ID)
    

    Is there any good reason to use org.openudid.OpenUDID_service at all?

    opened by mingfai 6
  • Add new consent category for metrics data

    Add new consent category for metrics data

    Metrics data are sent only if session consent is given. If you don't want to track the session, it's impossible to get the metrics data.

    This MR create a new category called "metrics" that used only to send metrics data. For backwards compatibility, metrics data are also sent if you give consent for "session".

    Feel free to make any changes or just capture the idea behind this MR.

    opened by angelix 1
  • Servers with TLSv1.3 get authType generic leads to connection failure

    Servers with TLSv1.3 get authType generic leads to connection failure

    On a server with nginx and

    ssl-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-protocols TLSv1.2 TLSv1.3
    

    the authType here

    https://github.com/Countly/countly-sdk-android/blob/0183e779d641f5575105f12679ab59c40e171652/sdk/src/main/java/ly/count/android/sdk/CertificateTrustManager.java#L65

    gets GENERIC as value, and so it fails to proceed.

    Expected Behavior

    Working TLSv1.3 support

    Current Behavior

    Failure to test trust successfully

    ###Fix add GENERIC as valid value to condition

    Your Environment

    Server with TLSv1.3 support:

    - Certificate type: X.509
    - Got a certificate list of 3 certificates.
    - Certificate[0] info:
     - subject `CN=xxxx', issuer `CN=R3,O=Let's Encrypt,C=US', serial 0x04e9144a791109259cb796a9f14c167d08c4, RSA key 2048 bits, signed using RSA-SHA256, activated `2021-10-01 14:09:11 UTC', expires `2021-12-30 14:09:10 UTC', pin-sha256="kXQROHwb/fw4tN6SKZYOyuUESd13exPRf0Bjk+AC3y4="
    	Public Key ID:
    		sha1:f93e26e75fbc8c8951fc49a0a24c4dddea18eeb1
    		sha256:917411387c1bfdfc38b4de9229960ecae50449dd777b13d17f406393e002df2e
    	Public Key PIN:
    		pin-sha256:kXQROHwb/fw4tN6SKZYOyuUESd13exPRf0Bjk+AC3y4=
    
    - Certificate[1] info:
     - subject `CN=R3,O=Let's Encrypt,C=US', issuer `CN=ISRG Root X1,O=Internet Security Research Group,C=US', serial 0x00912b084acf0c18a753f6d62e25a75f5a, RSA key 2048 bits, signed using RSA-SHA256, activated `2020-09-04 00:00:00 UTC', expires `2025-09-15 16:00:00 UTC', pin-sha256="jQJTbIh0grw0/1TkHSumWb+Fs0Ggogr621gT3PvPKG0="
    - Certificate[2] info:
     - subject `CN=ISRG Root X1,O=Internet Security Research Group,C=US', issuer `CN=DST Root CA X3,O=Digital Signature Trust Co.', serial 0x4001772137d4e942b8ee76aa3c640ab7, RSA key 4096 bits, signed using RSA-SHA256, activated `2021-01-20 19:14:03 UTC', expires `2024-09-30 18:14:03 UTC', pin-sha256="C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M="
    - Status: The certificate is trusted.
    - Description: (TLS1.3-X.509)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
    - Options:
    - Handshake was completed
    

    Server with TLSv1.3 support disabled:

    - Certificate type: X.509
    - Got a certificate list of 3 certificates.
    - Certificate[0] info:
     - subject `CN=xxxxx', issuer `CN=R3,O=Let's Encrypt,C=US', serial 0x04e9144a791109259cb796a9f14c167d08c4, RSA key 2048 bits, signed using RSA-SHA256, activated `2021-10-01 14:09:11 UTC', expires `2021-12-30 14:09:10 UTC', pin-sha256="kXQROHwb/fw4tN6SKZYOyuUESd13exPRf0Bjk+AC3y4="
    	Public Key ID:
    		sha1:f93e26e75fbc8c8951fc49a0a24c4dddea18eeb1
    		sha256:917411387c1bfdfc38b4de9229960ecae50449dd777b13d17f406393e002df2e
    	Public Key PIN:
    		pin-sha256:kXQROHwb/fw4tN6SKZYOyuUESd13exPRf0Bjk+AC3y4=
    
    - Certificate[1] info:
     - subject `CN=R3,O=Let's Encrypt,C=US', issuer `CN=ISRG Root X1,O=Internet Security Research Group,C=US', serial 0x00912b084acf0c18a753f6d62e25a75f5a, RSA key 2048 bits, signed using RSA-SHA256, activated `2020-09-04 00:00:00 UTC', expires `2025-09-15 16:00:00 UTC', pin-sha256="jQJTbIh0grw0/1TkHSumWb+Fs0Ggogr621gT3PvPKG0="
    - Certificate[2] info:
     - subject `CN=ISRG Root X1,O=Internet Security Research Group,C=US', issuer `CN=DST Root CA X3,O=Digital Signature Trust Co.', serial 0x4001772137d4e942b8ee76aa3c640ab7, RSA key 4096 bits, signed using RSA-SHA256, activated `2021-01-20 19:14:03 UTC', expires `2024-09-30 18:14:03 UTC', pin-sha256="C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M="
    - Status: The certificate is trusted.
    - Description: (TLS1.2-X.509)-(ECDHE-X25519)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
    - Session ID: 42:8F:A4:4D:C4:9E:1E:42:67:56:0E:20:19:94:62:C2:D0:51:A0:1D:B8:73:B9:AC:F2:E7:4E:E6:DC:60:CC:C9
    - Options: extended master secret, safe renegotiation,
    - Handshake was completed
    
    
    
    opened by appcoders 6
  • Event gets associated with wrong user

    Event gets associated with wrong user

    Events recorded after changeDeviceIdWithoutMerge are still associated with the previous user.

    Code to reproduce:

    import android.app.Activity
    import android.os.Bundle
    import ly.count.android.sdk.Countly
    import ly.count.android.sdk.CountlyConfig
    import ly.count.android.sdk.DeviceId
    
    class DemoActivity : Activity() {
    
        private lateinit var countly: Countly
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val config = CountlyConfig(
                application,
                CountlyIntegration.COUNTLY_APP_KEY,
                CountlyIntegration.COUNTLY_SERVER_URL
            ).apply {
                setHttpPostForced(true)
                setDeviceId("dg-20210507-test1")
                setLoggingEnabled(true)
                setParameterTamperingProtectionSalt(CountlyIntegration.COUNTLY_SALT)
            }
    
            countly = Countly.sharedInstance().init(config)
    
            countly.events().recordEvent("Test", mapOf("event" to "1"))
    
            countly.changeDeviceIdWithoutMerge(DeviceId.Type.DEVELOPER_SUPPLIED, "dg-20210507-test2")
            countly.events().recordEvent("Test2", mapOf("event" to "2"))
    
            countly.changeDeviceIdWithoutMerge(DeviceId.Type.DEVELOPER_SUPPLIED, "dg-20210507-test1")
            countly.events().recordEvent("Test", mapOf("event" to "3"))
    
            countly.doStoredRequests() // send data to server
        }
    
        override fun onStart() {
            super.onStart()
            countly.onStart(this)
        }
    
        override fun onStop() {
            super.onStop()
            countly.onStop()
        }
    }
    

    The real application is much more complex and initialization is happening in Application.onCreate, but the issue is also reproducible with the code provided above.

    Expected Behavior

    User with deviceId == "dg-20210507-test1" should have the events:

    {"key":"Test", "segmentation":{"event":"1"}}
    {"key":"Test", "segmentation":{"event":"3"}}
    

    User with deviceId == "dg-20210507-test2" should have the events:

    {"key":"Test2", "segmentation":{"event":"2"}}
    

    Current Behavior

    User with deviceId == "dg-20210507-test1" receives all events:

    {"key":"Test", "segmentation":{"event":"1"}}
    {"key":"Test2", "segmentation":{"event":"2"}}
    {"key":"Test", "segmentation":{"event":"3"}}
    

    User with deviceId == "dg-20210507-test2" doesn't receive any events:

    Screenshots (if appropriate):

    Screenshot of the current behavior from the user profile of user with deviceId == "dg-20210507-test1": Screenshot 2021-05-07 at 19 08 23

    Possible Solution

    No proposal. I saw that code that should make sure that events are not associated with the wrong deviceId is in place, but it doesn't seem to work in the provided scenario. Could be a race condition when events are tracked too fast after each other.

    Steps to Reproduce (for bugs)

    1. Copy code provided at top into an Android project.
    2. Insert proper values for CountlyIntegration.COUNTLY_APP_KEY, CountlyIntegration.COUNTLY_SERVER_URL, CountlyIntegration.COUNTLY_SALT.
    3. Run the app.
    4. Observe events in User Profiles on Countly Server.

    More Description

    Our app allows to switch users. We noticed that some events are associated with the wrong user. Especially those that are happening close to the changeDeviceIdWithoutMerge call. We tried to eliminate our own code as root cause and then tried to reproduce the issue with a minimal example. The result is the code provided in this issue.

    Your Environment

    • Countly Android SDK version: 20.11.8
    • Your Android version: Android 11
    • Your device: Pixel 3a
    • Any changes you have made to this SDK: none. It's the version provided by your maven repository.
    opened by xa17d 2
  • Crashes get lost

    Crashes get lost

    When the user is offline or server is stopped, and a crash occurs, the crash get lost! After many tests and read the this sdk source code, i found the issue. When an error occurs, the app stops quickly and the caching not apply..

    https://github.com/Countly/countly-sdk-android/blob/dd79709acce513d4c8564fe06c66ab39d9a02de1/sdk/src/main/java/ly/count/android/sdk/CountlyStore.java
    

    and i solved it temporarily by adding a long run Thread.UncaughtExceptionHandler to my App.kt class, to delay the stop time

    val def = Thread.getDefaultUncaughtExceptionHandler()
    val handler = Thread.UncaughtExceptionHandler { t, e ->
        sleep(500)
        def?.uncaughtException(t, e)
    }
    Thread.setDefaultUncaughtExceptionHandler(handler)
    
    val config = CountlyConfig(this, countlyAppKey, countlyUrl)
    ...
    Countly.sharedInstance().init(config)
    
    
    opened by am3n 2
  • Introduce ConnectionInterceptor for individual connection processing

    Introduce ConnectionInterceptor for individual connection processing

    Motivation

    Currently, it is only possible to set static http header values once. It is not possible to add header values which change with each network request. We have the need to add headers which change with each request, because we sign each request (request method, request body and some other meta information) with a timestamp in our app.

    What changed

    Similarly to Okhttp, this introduces an interceptor interface ConnectionInterceptor to process each connection, i.e. add custom header which change with each request. It can be set at the beginning and will be called for each network request.

    Example

    ConnectionInterceptor interceptor = new ConnectionInterceptor() {
        @Override public HttpURLConnection intercept(HttpURLConnection connection, byte[] body) {
            connection.setRequestProperty("Prop", new Date().toString() + " super secret signature");
            return connection;
        }
    };
    Countly.sharedInstance().setConnectionInterceptor(interceptor)
    
    opened by vtuan10 3
  • Custom Properties cant be deleted.

    Custom Properties cant be deleted.

    I want to be able to delete a custom property I have set on a user, it that property is no longer relevant.

    Expected Behavior

    As per the API; https://api.count.ly/reference#section-user-details "If you set value as null, you will delete the property."

    however, currently in ly.count.sdk.internal.UserEditorImpl, if the value is null it is deleted from the request, and not sent to the countly server.

    Possible Solution

    Change ly.count.sdk.internal.UserEditorImpl.perform so that if null is passed in for a custom property, that null is kept, and sent to the api, so that the property can be removed.

    default: if (value == null || value instanceof String || value instanceof Integer || value instanceof Float || value instanceof Double || value instanceof Boolean || value instanceof String[] || value instanceof Integer[] || value instanceof Float[] || value instanceof Double[] || value instanceof Boolean[] || value instanceof Object[]) { if (!changes.has(CUSTOM)) { changes.put(CUSTOM, new JSONObject()); } changes.getJSONObject(CUSTOM).put(key, value); if (value == null) { user.custom.remove(key); } else { user.custom.put(key, value); } } else { L.wtf("Type of value " + value + " '" + value.getClass().getSimpleName() + "' is not supported yet, thus user property is not stored"); }

    Your Environment

    I am using core-19.09-sdk2-rc.jar java-19.09-sdk2-rc.jar

    opened by jon0hopper 0
Releases(22.06.2)
  • 22.06.2(Dec 5, 2022)

    • Fixed a bug that would throw a null pointer exception when calling "CountlyPush.displayNotification " and CountlyPush was not initialized
    Source code(tar.gz)
    Source code(zip)
  • 22.06.1(Nov 28, 2022)

  • 22.06.0(Oct 2, 2022)

    • Fatal crash reports will now be written in sync mode to shared preferences

    • Added explicit storage mode where the event queue and request queue are not writen to persistent storage until a signal is given

    • Added mitigations for rare crashes while updating remote config values

    • Adding a init time cleanup procedure to remove any leftover temporary id requests

    • Removed the deprecated "disableLocation" method

    • Removed the deprecated "setLocation" method

    Source code(tar.gz)
    Source code(zip)
  • 22.02.3(Sep 5, 2022)

    • Added CountlyConfigPush object which is used during CountlyPush init.
    • Added a way to add allowed package names for push notification intent security.
    • Added a way to add allowed class names for push notification intent security.
    Source code(tar.gz)
    Source code(zip)
  • 22.02.2(Aug 31, 2022)

  • 22.02.1(Aug 11, 2022)

  • 22.02.0(Aug 5, 2022)

    • Fixed notification trampoline restrictions in Android 12 using reverse activity trampolining implementation.
    • Adding a call to provide user properties during initialization.
    Source code(tar.gz)
    Source code(zip)
  • 21.11.2(May 25, 2022)

    • Fixed bug that caused crashes when migrating from older versions that don't have a device ID type stored. When migrating from no device ID and no type, SDK will fall back to a generated ID. When migrating from device ID and no type, SDK will set id type to 'DEVELOPER_SUPPLIED' if a custom ID was provided during init. Otherwise the new type will be 'OPEN_UDID'. Adding handling for additional edge cases.
    Source code(tar.gz)
    Source code(zip)
  • 21.11.1(May 12, 2022)

  • 21.11.0(May 10, 2022)

    • !! Major breaking change !! Deprecating "ADVERTISING_ID" as device ID generation strategy. SDK will fall back to 'OPEN_UDID'. All "ADVERTISING_ID" device ID's will have their type changed to "OPEN_UDID". If the device will have a "null" device ID, a random one will be generated.

    • !! Major breaking change !! Changing device ID without merging will now clear all consent. It has to be given again after this operation.

    • !! Major breaking change !! Entering temporary ID mode will now clear all consent. It has to be given again after this operation.

    • ! Minor breaking change ! Feedback widget callback has an additional callback. This will cause a compilation error that is trivial to fix by adding the override for the missing call.

    • ! Minor breaking change ! Automatic "AdvertisingId" attribution has been removed from the SDK. A call is added for recording provided attribution values.

    • ! Minor breaking change ! Automatic install referrer attribution in play stores has been removed. A call is added for recording such provided values.

    • ! Minor breaking change ! Orientation tracking is now enabled by default. Can be turned off during init.

    • ! Minor breaking change ! A few internal SDK limits are now introduced. The following limits are adjustable at initialization:

      • Maximum amount of provided segmentation in now 30 entries by default.
      • Maximum amount of breadcrumbs that can be recorded at once is now 100 by default.
    • Device ID can now be changed when no consent is given

    • Push notification now display/use the sent badge number. It's visualization depends on the launcher.

    • Added new calls to report attribution.

    • When recording internal events with 'recordEvent', the respective feature consent will now be checked instead of the 'events' consent.

    • Consent changes will now send the whole consent state and not just the "delta"

    • Deprecated old user profile calls. Introduced a new API by which to change them.

    • Added platform information to push actioned events

    • Fixed bug where, on the start of a new session, the first view was not identified correctly

    • Fixed bug where the rating widget callback would not be called when the widget is closed and there is no error

    • Fixed potential deadlock issue

    • Removed the deprecated "init" methods

    • Removed the deprecated "recordEvent" methods

    • Removed the deprecated "changeDeviceId" methods

    • Removed the deprecated "setViewTracking" method

    • Removed the deprecated "isViewTrackingEnabled" method

    • Removed the deprecated "recordView" methods

    • Removed the deprecated "setCustomCrashSegments" method

    • Removed the deprecated "addCrashBreadcrumb" method

    • Removed the deprecated "recordHandledException" methods

    • Removed the deprecated "recordUnhandledException" methods

    • Removed the deprecated "enableCrashReporting" method

    • Removed the deprecated "startEvent" method

    • Removed the deprecated "endEvent" methods

    • Removed the deprecated "setDisableUpdateSessionRequests" method

    • Removed the deprecated "enableParameterTamperingProtection" method

    • Removed the deprecated "enablePublicKeyPinning" method

    • Removed the deprecated "enableCertificatePinning" method

    • Removed the deprecated "setPushIntentAddMetadata" method

    • Removed the deprecated "setEnableAttribution" method

    • Removed the deprecated "setEventQueueSizeToSend" method

    • Removed the deprecated "setStarRatingDialogTexts" method

    • Removed the deprecated "setIfStarRatingShownAutomatically" method

    • Removed the deprecated "setStarRatingDisableAskingForEachAppVersion" method

    • Removed the deprecated "setAutomaticStarRatingSessionLimit" method

    • Removed the deprecated "getAutomaticStarRatingSessionLimit" method

    • Removed the deprecated "getStarRatingsCurrentVersionsSessionCount" method

    • Removed the deprecated "clearAutomaticStarRatingSessionCount" method

    • Removed the deprecated "setIfStarRatingDialogIsCancellable" method

    • Removed the deprecated "setHttpPostForced" method

    • Removed the deprecated "setShouldIgnoreCrawlers" method

    • Removed the deprecated "addAppCrawlerName" method

    • Removed the deprecated "setRequiresConsent" method

    • Removed the deprecated "createFeatureGroup" method

    • Removed the deprecated "setConsentFeatureGroup" method

    • Removed the deprecated "setConsent" method

    • Removed the deprecated "giveConsent" method

    • Removed the deprecated "removeConsent" method

    • Removed the deprecated "removeConsentAll" method

    • Removed the deprecated "getConsent" method

    • Removed the deprecated "checkAllConsent" method

    • Removed the deprecated "showFeedbackPopup" method

    • Removed the deprecated "setRemoteConfigAutomaticDownload" method

    • Removed the deprecated "remoteConfigUpdate" method

    • Removed the deprecated "updateRemoteConfigForKeysOnly" method

    • Removed the deprecated "updateRemoteConfigExceptKeys" method

    • Removed the deprecated "getRemoteConfigValueForKey" method

    • Removed the deprecated "remoteConfigClearValues" method

    • Removed the deprecated "addCustomNetworkRequestHeaders" method

    • Removed the deprecated "setLoggingEnabled" method

    Source code(tar.gz)
    Source code(zip)
  • 20.11.12(Jan 26, 2022)

    • Fixed bug due to "CLOSE_SYSTEM_DIALOGS" permission denial
    • Adding an init time configuration option to set the maximum request queue size
    • Updating the "compileSdkVersion" and "targetSdkVersion" to "31".
    • Updating the "buildToolsVersion" to "31.0.0".
    Source code(tar.gz)
    Source code(zip)
  • 20.11.11(Nov 12, 2021)

    • Fixed a bug where events would be sent with a larger delay if SDK callbacks are not called
    • Fixed a bug where "platform" and "app_version" were provided incorectly when retrieving the feedback widget data
    Source code(tar.gz)
    Source code(zip)
  • 20.11.10(Aug 11, 2021)

  • 20.11.9(Aug 2, 2021)

    • Moving a push related broadcast receiver decleration to the manifest to comply with 'PendingIntent' checks
    • Fixed issue with star rating lowest allowed value. Changing it from 0 to 1.
    • Fixed bug that would prevent certain codepath to be executed if the Application class was not provided during init.
    • Added additional protections in remote config logic to protect against rare crashes
    • Increasing default event threshold to 100.
    • Printing approximate data usage in logs when sending requests
    Source code(tar.gz)
    Source code(zip)
  • 20.11.8(Apr 26, 2021)

  • 20.11.7(Apr 7, 2021)

  • 20.11.6(Feb 23, 2021)

    • Fixed init time bug where the context from the provided application class was not used.
    • Fixed init time bug which happened when location was disabled during init.
    Source code(tar.gz)
    Source code(zip)
  • 20.11.5(Feb 12, 2021)

  • 20.11.4(Feb 1, 2021)

    • Added a way to retrieve feedback widget data and manually report them
    • Fixed bug where network request were retried too soon after a failed request
    Source code(tar.gz)
    Source code(zip)
  • 20.11.3(Jan 14, 2021)

  • 20.11.2(Dec 8, 2020)

    • Added SDK log listener
    • Refactored all logs to use the new logging mechanism
    • Fixed bug where manual session control calls were working even when not enabled
    Source code(tar.gz)
    Source code(zip)
  • 20.11.1(Nov 27, 2020)

    • Lessened push notification security restrictions
    • Added a default way to acquire app start timestamp for APM
    • Added a way to override the current app start timestamp for APM
    • Added manual trigger for when app has finished loading for APM
    • Added manual foreground/background triggers for APM
    Source code(tar.gz)
    Source code(zip)
  • 20.11.0(Nov 8, 2020)

    • !! Consent change !! To record orientation you now need to give "user" consent

    • !! Consent change !! To use remote config, you now need to give "remote-config" consent

    • !! Push breaking changes !! Due to a security vulnerability the following permission need to be added to your app manifest: ' <uses-permission android:name="${applicationId}.CountlyPush.BROADCAST_PERMISSION" /> ' To make these breaking changes noticable, the broadcast listener id 'NOTIFICATION_BROADCAST' has been replaced with 'SECURE_NOTIFICATION_BROADCAST'

    • Added survey, nps feature

    • Added retries to push media download

    • Added call that removes all server requests that don't have the currently set appKey

    • Added call that updates all server requests so that all of them have the currently set appKey

    • Update breakpad for native exception catching

    • Symbol upload tool now sends the used breakpad version

    • Reworked openID device ID to not be a separate service

    • Sending device type (phone, tablet, tv) as part of metrics

    • Reworked location data persistence and when it is sent. It's recommended to recheck your app to see if it's still behaving as expected.

    • Deprecated CountlyConfig constructor that takes 'Context'. Added new constructor that also takes the Application class instead of 'Context'

    • Initialising the SDK without providing the application class is not deprecated

    • Fixed a push consent edge case bug where it would have been counted when set in the past

    • Fixed a push consent bug where 'anyConsent' would have returned true when no consent would have been set

    • Fixed a bug regarding temporary ID mode transitioning device ID's which would merge it to the previous value

    • Fixed init time openUDID bug which made it less persistent than required

    • Fixed potential multithreaded synchronization issues

    • Fixed location url encoding bug

    • Fixed init issue where the device ID was not saved and could be changed by changing it's value during next init

    Source code(tar.gz)
    Source code(zip)
  • 20.04.5(Aug 21, 2020)

    • Replacing sha-1 hash with sha-256 hash for requests.
    • Adding apm calls for cancelTrace, cancelAllTraces, recordNetworkTrace
    • Adding option to use Huawei push notifications
    • making tweaks to APM key validation logic
    Source code(tar.gz)
    Source code(zip)
  • 20.04.4(Jul 24, 2020)

    • Adding metric override feature
    • Adding functionality to override SDK name and SDK version strings
    • Fixed a issue in the network request retry logic
    • Removed requirement for any consent to be set before device ID can be changed.
    • Mitigating issue which would happen if push token is refreshed before SDK is initialized.
    • Fixed the sending of empty event collections in cases where event sending was forced.
    Source code(tar.gz)
    Source code(zip)
  • 20.04.3(Jun 13, 2020)

    • Adding fallback cache to CountlyPush for cases where the SDK is not initialised
    • Fixed bug which happened when consent was required but no consent was provided during init
    Source code(tar.gz)
    Source code(zip)
  • 20.04.2(May 21, 2020)

  • 20.04.1(May 13, 2020)

  • 20.04(Apr 30, 2020)

    • Adding functionality for filtering crashes
    • Adding functionality to set segmentation for automatic and manual views
    • Adding functionality to ignore activities for automatic view tracking
    • Adding functionality to track orientation changes
    • Adding call to manually record user rating without showing any UI
    • Adding call to record a event with a given timestamp
    • Adding call to cancel a timed event
    • Adding manual session control
    • Adding option to set tamper protection salt in config object
    • Adding calls to give and remove consent to all features at the same time
    • Adding a way to change the session update timer interval
    • Adding call to set notification accent color
    • Adding APM functinality to record app start time
    • Adding APM functinality to record custom traces
    • Adding APM functinality to record network request traces
    • Adding APM functinality to record app time spent in foreground and background
    • Adding remote config call to get all saved values
    • Moving crash, event, view, rating related calls to a seperate modules
    • Deprecating functions that are being put into modules
    • Migrated to AndroidX
    • Improved internal time management which fixes inconsistencies that could arrise on day changes
    • Fixed a bug where deep links from notifications did not include the sent message as part of the intent
    • Removing depracated "addCrashLog" call
    • Removing depracated "logException" call
    • Removing depracated "setCustomUserData" call
    • Removing depracated "setUserData" call
    Source code(tar.gz)
    Source code(zip)
  • 19.09.3(Apr 1, 2020)

Owner
Countly Team
Countly is the most extensive product analytics and innovation platform to understand and enhance customer journeys in web, desktop and mobile applications
Countly Team
Tiny tracking lib for Google Analytics.

BloodHoud Tiny library for tracking screens and events with google analytics and / or firebase analytics. How to install repositories { maven {

Jan Rabe 22 Oct 5, 2022
A tool to install components of the Android SDK into a Maven repository or repository manager to use with the Android Maven Plugin, Gradle and other tools.

Maven Android SDK Deployer Original author including numerous fixes and changes: Manfred Moser [email protected] at simpligility technologies i

simpligility 1.4k Dec 27, 2022
A tool to install components of the Android SDK into a Maven repository or repository manager to use with the Android Maven Plugin, Gradle and other tools.

Maven Android SDK Deployer Original author including numerous fixes and changes: Manfred Moser [email protected] at simpligility technologies i

simpligility 1.4k Dec 27, 2022
Official Mixpanel Android SDK

Latest Version March 25, 2021 - v5.8.8 Table of Contents Quick Start Guide Installation Integration I want to know more! Want to Contribute? Changelog

Mixpanel, Inc 976 Dec 15, 2022
CleverTap Android SDK

CleverTap Android SDKs ?? Introduction (Back to top) The CleverTap Android SDK for Mobile Customer Engagement and Analytics solutions CleverTap brings

CleverTap 71 Dec 2, 2022
A simple utility to remove unused resources in your Android app to lower the size of the APK. It's based on the Android lint tool output.

android-resource-remover android-resource-remover is utility that removes unused resources reported by Android Lint from your project. The goal is to

Keepsafe 1.3k Dec 16, 2022
This is a Android Studio/ IntelliJ IDEA plugin to localize your Android app, translate your string resources automactically.

#Android Localizationer This is a Android Studio/ IntelliJ IDEA plugin to localize your Android app, translate your string resources automactically. T

Wesley Lin 822 Dec 8, 2022
Automated-build-android-app-with-github-action - CI/CD Automated Build Android App Bundle / APK / Signed With Github Action

Automated Build Android With Using Github Action Project Github Action Script Us

Faisal Amir 34 Dec 19, 2022
proguard resource for Android by wechat team

AndResGuard Read this in other languages: English, 简体中文. AndResGuard is a tooling for reducing your apk size, it works like the ProGuard for Java sour

shwenzhang 8.1k Jan 9, 2023
A super fast build tool for Android, an alternative to Instant Run

Freeline Freeline is a super fast build tool for Android and an alternative to Instant Run. Caching reusable class files and resource indices, it enab

Alibaba 5.5k Jan 2, 2023
Command-line tool to count per-package methods in Android .dex files

dex-method-counts Simple tool to output per-package method counts in an Android DEX executable grouped by package, to aid in getting under the 65,536

Mihai Parparita 2.6k Nov 25, 2022
View Inspection Toolbar for Android Development

View Inspector Plugin View inspection toolbar for android development. Features Boundary show outlines show margins show paddings Layer Scalpel featur

Fumihiro Xue (Peter Hsieh) 2.2k Nov 14, 2022
Make Android screenshots of scrollable screen content

scrollscreenshot Make Android screenshots of scrollable screen content - brought to you by PGS Software SA This tool makes a number of screenshots, sc

PGS Software 714 Dec 7, 2022
🍼Debug Bottle is an Android runtime debug / develop tools written using kotlin language.

???? 中文 / ???? 日本語 / ???? English ?? Debug Bottle An Android debug / develop tools written using Kotlin language. All the features in Debug bottle are

Yuriel Arlencloyn 846 Nov 14, 2022
[] Dissect layout traversals on Android

Probe Dissect layout traversals on Android. Features Intercept View methods. onMeasure(int, int) onLayout(boolean, int, int, int, int) draw(Canvas) an

Lucas Rocha 555 Nov 25, 2022
Android Library Finder

alfi Android Library Finder Search through thousands of android libraries that can help you scale your projects elegantly Usage Search for something a

César Ferreira 509 Dec 8, 2022
Annotation based simple API flavored with AOP to handle new Android runtime permission model

Let Annotation based simple API flavoured with AOP to handle new Android runtime permission model. If you check Google's Samples about the new permiss

Can Elmas 530 Nov 25, 2022
Combines tools for fast android app devlopment

Android - Rapid Test Driven Development Combine tools to generate most of the boilerplate code. Examples how to test different aspects of an android a

Nico Küchler 379 Nov 25, 2022