GithubHelp home page GithubHelp logo

segmentio / analytics-android Goto Github PK

View Code? Open in Web Editor NEW
375.0 375.0 213.0 78.2 MB

The hassle-free way to add analytics to your Android app.

Home Page: https://segment.com/docs/sources/mobile/android/

License: MIT License

Shell 0.14% Java 55.58% Kotlin 44.27%

analytics-android's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

analytics-android's Issues

Database bug, database not being closed

Running with the master branch of today..

03-26 14:58:50.411: E/Database(2825): close() was never explicitly called on database 'countly' 
03-26 14:58:50.411: E/Database(2825): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1864)
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:822)
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:856)
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:849)
03-26 14:58:50.411: E/Database(2825):   at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:556)
03-26 14:58:50.411: E/Database(2825):   at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
03-26 14:58:50.411: E/Database(2825):   at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
03-26 14:58:50.411: E/Database(2825):   at ly.count.android.api.CountlyDB.getEvents(Countly.java:596)
03-26 14:58:50.411: E/Database(2825):   at ly.count.android.api.EventQueue.<init>(Countly.java:378)
03-26 14:58:50.411: E/Database(2825):   at ly.count.android.api.Countly.init(Countly.java:75)
03-26 14:58:50.411: E/Database(2825):   at io.segment.android.integrations.CountlyIntegration.onCreate(CountlyIntegration.java:51)
03-26 14:58:50.411: E/Database(2825):   at io.segment.android.integration.IntegrationManager$2.run(IntegrationManager.java:217)
03-26 14:58:50.411: E/Database(2825):   at io.segment.android.integration.IntegrationManager.runOperation(IntegrationManager.java:182)
03-26 14:58:50.411: E/Database(2825):   at io.segment.android.integration.IntegrationManager.onCreate(IntegrationManager.java:213)
03-26 14:58:50.411: E/Database(2825):   at io.segment.android.Analytics.onCreate(Analytics.java:93)

ConcurrentModificationException

Got this error from segment.io library.

java.util.ConcurrentModificationException
       at java.util.HashMap$HashIterator.nextEntry(HashMap.java:796)
       at java.util.HashMap$KeyIterator.next(HashMap.java:823)
       at android.database.sqlite.SQLiteDatabase.removeMeFromActive(SQLiteDatabase.java:950)
       at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:980)
       at io.segment.android.db.PayloadDatabase.getEvents(PayloadDatabase.java:248)
       at io.segment.android.db.PayloadDatabaseThread$2.run(PayloadDatabaseThread.java:52)
       at android.os.Handler.handleCallback(Handler.java:587)
       at android.os.Handler.dispatchMessage(Handler.java:92)
       at android.os.Looper.loop(Looper.java:130)
       at io.segment.android.utils.LooperThreadWithHandler.run(LooperThreadWithHandler.java:32)

Error generating final archive with 0.6.12

[2014-05-09 13:01:02 - MGMainActivity] Error generating final archive:
Found duplicate file for APK: AndroidManifest.xml
Origin 1: /home/rednamer/Work/aliceoid/Aliceoid/bin/resources.ap_
Origin 2:
/home/rednamer/Work/aliceoid/Aliceoid/libs/analytics-android-0.6.12.jar

Bug in database entrie

When inserts a string with ' (single quotes) like "Newell's Old Boys" the app crashes:

FATAL EXCEPTION: main
android.database.sqlite.SQLiteException: near "s": syntax error (code 1): , while compiling: INSERT OR REPLACE INTO EVENTS(ID, EVENT) VALUES(1, '{"events":[{"timestamp":1396537600,"sum":0,"segmentation":{"ACAO":"Create"},"count":0,"key":"ACCESS SCREEM ONE"},{"timestamp":1396537600,"sum":0,"segmentation":{},"count":0,"key":"ACCESS SCREEM ONE"},{"timestamp":1396537600,"sum":0,"segmentation":{},"count":0,"key":"ACCESS SCREEM ONE"},{"timestamp":1396537600,"sum":0,"segmentation":{},"count":0,"key":"ACCESS SCREEM ONE"},{"timestamp":1396537600,"sum":0,"segmentation":{"TIPO":"ACCESS SCREEM ONE"},"count":0,"key":"ACCESS SCREEM ONE"},{"timestamp":1396537600,"sum":0,"segmentation":{"ID":"712","NOME":"Newell's Old Boys"},"count":0,"key":"ACCESS SCREEM ONE"}]}');
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1090)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:663)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1769)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1700)
at ly.count.android.api.CountlyDB.saveEvents(Countly.java:646)
at ly.count.android.api.EventQueue.recordEvent(Countly.java:496)
at ly.count.android.api.Countly.recordEvent(Countly.java:127)
at io.segment.android.integrations.CountlyIntegration.track(CountlyIntegration.java:89)
at io.segment.android.integration.IntegrationManager$9.run(IntegrationManager.java:332)
at io.segment.android.integration.IntegrationManager.runOperation(IntegrationManager.java:182)
at io.segment.android.integration.IntegrationManager.track(IntegrationManager.java:326)
at io.segment.android.Analytics.track(Analytics.java:1087)
at io.segment.android.Analytics.track(Analytics.java:969)

Don't use Android ID.

It has been known for quite some time that you should not use the Android Device ID.

Your OpenUUID class seem to use this:

Please read Google Blog

Expose Instances of Bundled Integrations

Have a way for users to get the instance that we are using in our integration so they can share it.

Potential usability : If they turn of the integration on the server, we won't actually initialize it through our library, so if they call any methods for the integration later, users will have to make sure they initialize it first.

Foo foo = Analytics.getIntegrations().get("foo").getInstance();

// if integration was turned of in the server, then foo is actually not initalized, and may be null.
// This could lead to any following calls to it throw NPE.
// The burden of performing those null checks would be on the user.

CursorWindowAllocationException in PayloadDatabase.getEvents()

Hi Folks,
Have you ever experienced this before.

02:58:28 // android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. 
02:58:28 // at android.database.CursorWindow.<init>(CursorWindow.java:104) 
02:58:28 // at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198) 
02:58:28 // at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139) 
02:58:28 // at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) 
02:58:28 // at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197) 
02:58:28 // at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245) 
02:58:28 // at io.segment.android.db.PayloadDatabase.getEvents(PayloadDatabase.java:230) 
02:58:28 // at io.segment.android.db.PayloadDatabaseThread$2.run(PayloadDatabaseThread.java:52) 
02:58:28 // at android.os.Handler.handleCallback(Handler.java:725) 
02:58:28 // at android.os.Handler.dispatchMessage(Handler.java:92) 
02:58:28 // at android.os.Looper.loop(Looper.java:137) 
02:58:28 // at io.segment.android.utils.LooperThreadWithHandler.run(LooperThreadWithHandler.java:32) 

The Cursor is closed in the finally as expected

finally {
                try {
                    if (cursor != null) cursor.close();
                    if (db != null) db.close();
                } catch (SQLiteException e) {
                    Logger.e("Failed to close db cursor: " + 
                            Log.getStackTraceString(e));
                }
            }

Documentation error about method reset()

Hi, I found that the documentantion of Android Library its wrong, on step 4 you make a call to Static method reset() but the signature of that method on Analytics.java its not Static, showing an error when try to follow the documentation.

Thanks for your time.

César Pardo

Analytics.screen() ignored on Mixpanel

Hi,
As mentioned in the title, events from Analytics.screen() are ignored on Mixpanel.
I know that mixpanel does not support specifically screen() events. However in the segmentio iOS SDK, screen() events are sent to Mixpanel as track() events.

Wouldn't it be logical to have the same behaviour in the Android SDK ?

Thanks for the help,
Lukas

Include requestId

helps with dedup, logging, and debugging (once implemented server-side)

NullPointerException #27

java.lang.NullPointerException
       at ly.count.android.api.DeviceInfo.getResolution(Countly.java:300)
       at ly.count.android.api.DeviceInfo.getMetrics(Countly.java:345)
       at ly.count.android.api.ConnectionQueue.beginSession(Countly.java:187)
       at ly.count.android.api.Countly.onStartHelper(Countly.java:93)
       at ly.count.android.api.Countly.onStart(Countly.java:81)
       at io.segment.android.integrations.CountlyIntegration.onActivityStart(CountlyIntegration.java:58)
       at io.segment.android.integration.IntegrationManager$3.run(IntegrationManager.java:229)
       at io.segment.android.integration.IntegrationManager.runOperation(IntegrationManager.java:182)
       at io.segment.android.integration.IntegrationManager.onActivityStart(IntegrationManager.java:225)
       at io.segment.android.Analytics.activityStart(Analytics.java:169)
       at com.movile.futebol.activity.SplashActivity.onStart(SplashActivity.java:124)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1164)
       at android.app.Activity.performStart(Activity.java:5148)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2237)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2314)
       at android.app.ActivityThread.access$600(ActivityThread.java:144)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:150)
       at android.app.ActivityThread.main(ActivityThread.java:5147)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
       at dalvik.system.NativeStart.main(NativeStart.java)

Update Mixpanel to 4.2.0

It would be awesome to integrate the Mixpanel 4.2.0 library into segment.io to fix some issues we're having.

Flush continues after activity is destroyed and even after app is removed from recent apps

Affects version 0.6.2

I'm not extending TrackableActivity.

Here's how to reproduce...

public abstract class BootstrapActivity extends IckleFragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    boolean isDebug = 0 != ( getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE );
    Analytics.onCreate(this, Constants.App.SEGMENT_IO_WRITE_KEY, new Options().setDebug(isDebug));
}

@Override
public void onStart() {
    super.onStart();
    Analytics.activityStart(this);
}

@Override
protected void onResume() {
    super.onResume();
    Analytics.activityResume(this);
}

@Override
protected void onPause() {
    super.onPause();
    Analytics.activityPause(this);
}

@Override
protected void onStop() {
    super.onStop();
    Analytics.activityStop(this);
}

...

Producing some logs:

03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [Google Analytics] onActivityStart finished in : 0 milliseconds.
03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [Mixpanel] onActivityStart finished in : 0 milliseconds.
03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [All Providers] onActivityStart finished in : 1 milliseconds.
03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [Google Analytics] onActivityResume finished in : 0 milliseconds.
03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [Mixpanel] onActivityResume finished in : 0 milliseconds.
03-26 13:14:35.632 10795-10795/tv.pluto.android I/analytics﹕ [All Providers] onActivityResume finished in : 0 milliseconds.

....
03-26 13:14:38.515 10795-10817/tv.pluto.android I/analytics﹕ [Google Analytics] Flush finished in : 0 milliseconds.
03-26 13:14:38.515 10795-10817/tv.pluto.android I/analytics﹕ [Mixpanel] Flush finished in : 0 milliseconds.
03-26 13:14:38.515 10795-10817/tv.pluto.android I/analytics﹕ [All Providers] Flush finished in : 3 milliseconds.

...and when app is backgrounded....

03-26 13:16:46.620 10795-10795/tv.pluto.android I/analytics﹕ [Google Analytics] onActivityPause finished in : 0 milliseconds.
03-26 13:16:46.620 10795-10795/tv.pluto.android I/analytics﹕ [Mixpanel] onActivityPause finished in : 0 milliseconds.
03-26 13:16:46.620 10795-10795/tv.pluto.android I/analytics﹕ [All Providers] onActivityPause finished in : 0 milliseconds.
03-26 13:16:47.270 10795-10795/tv.pluto.android I/analytics﹕ [Google Analytics] onActivityStop finished in : 0 milliseconds.
03-26 13:16:47.270 10795-10795/tv.pluto.android I/analytics﹕ [Mixpanel] onActivityStop finished in : 0 milliseconds.
03-26 13:16:47.270 10795-10795/tv.pluto.android I/analytics﹕ [All Providers] onActivityStop finished in : 1 milliseconds.
03-26 13:16:48.632 10795-10817/tv.pluto.android I/analytics﹕ [Google Analytics] Flush finished in : 0 milliseconds.
03-26 13:16:48.632 10795-10817/tv.pluto.android I/analytics﹕ [Mixpanel] Flush finished in : 0 milliseconds.
03-26 13:16:48.632 10795-10817/tv.pluto.android I/analytics﹕ [All Providers] Flush finished in : 0 milliseconds.

INSTALL_FAILED_DEXOPT on Android 2.3.6

Impossible to run an application on Android 2.3.6 with analytics-android-0.6.5.jar.
INSTALL_FAILED_DEXOPT occurs on adb install

The library is included with build.gradle:

dependencies {
    ...
    compile files('libs/analytics-android-0.6.5.jar')
    ...
}

The app is installed correctly if I remove this line
Tried with 0.6.11 also with no success. (could't try with other versions, because I couldn't even build with them, but it's another issue)

Exceeding batch limit may cause duplicates

Repro test case by @kellyfj, thanks!

@Test
public void testTriggerTimerInteraction() throws InterruptedException {
    AnalyticsStatistics stats = Analytics.getStatistics();
    int flushAfter = Analytics.getOptions().getFlushAfter();
    int flushAt = Analytics.getOptions().getFlushAt();
    int flushAttempts = stats.getFlushAttempts().getCount();
    int flushes = stats.getFlushTime().getCount();
    for (int i = 0; i < flushAt + 5; i++) {
        Analytics.enqueue(TestCases.random());
    }
    // the flush after the trigger should have triggered a flush here
    flushAttempts += 1;
    flushes += 1;
    try {
        Thread.sleep(flushAfter + 250);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // the flush after timer should have triggered a flush here
    flushAttempts += 1;
    flushes += 1;
    Assert.assertEquals(flushes, stats.getFlushTime().getCount());
    //FJK: Given current issue Flush attempts will be 5 more than expected e.g. 2 vs 7
    Assert.assertEquals(flushAttempts, stats.getFlushAttempts().getCount());
}

database Bug

While running monkey test I got this log

android.database.sqlite.SQLiteException: unable to close due to unfinalised statements
       at android.database.sqlite.SQLiteDatabase.dbclose(SQLiteDatabase.java)
       at android.database.sqlite.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:325)
       at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:1025)
       at io.segment.android.db.PayloadDatabase.getEvents(PayloadDatabase.java:247)
       at io.segment.android.db.PayloadDatabaseThread$2.run(PayloadDatabaseThread.java:52)
       at android.os.Handler.handleCallback(Handler.java:587)
       at android.os.Handler.dispatchMessage(Handler.java:92)
       at android.os.Looper.loop(Looper.java:130)
       at io.segment.android.utils.LooperThreadWithHandler.run(LooperThreadWithHandler.java:32)

Hope it helps.

NullPointerException

Caused by: java.lang.NullPointerException
       at ly.count.android.api.DeviceInfo.getCarrier(Countly.java:331)
       at ly.count.android.api.DeviceInfo.getMetrics(Countly.java:362)
       at ly.count.android.api.ConnectionQueue.beginSession(Countly.java:191)
       at ly.count.android.api.Countly.onStartHelper(Countly.java:90)
       at ly.count.android.api.Countly.onStart(Countly.java:76)
       at io.segment.android.integrations.CountlyIntegration.onActivityStart(CountlyIntegration.java:59)
       at io.segment.android.integration.IntegrationManager$3.run(IntegrationManager.java:229)
       at io.segment.android.integration.IntegrationManager.runOperation(IntegrationManager.java:182)
       at io.segment.android.integration.IntegrationManager.onActivityStart(IntegrationManager.java:225)
       at io.segment.android.Analytics.activityStart(Analytics.java:169)

Duplicate Events

For sending events to the server, we have an integrations key in each payload that contains string-boolean pairs, each entry denoting whether the service is enabled for that integration.

Any integrations that are bundled, we'll have that key set to false so that we don't send via the server.

Unfortunately, we're re-using this integrations map to check whether we should also post the event to the bundled integration.

This means if we set mixpanel to false, it won't be sent to Mixpanel from the server, and it won't be sent to the bundled integration either. If we set it to true, then it will be sent by both the bundled integration and the server integration - causing duplicate events.

For the future, we'll probably want to use some sort of triplean (backed by an enum) variable, so users can decide whether something needs to be sent via the server integration, the bundled integration, or neither (both can probably be eliminated).

[Question] Why does the client use providers?

I'm pretty sure the whole point of your service is that I am sending requests to your server which in turn forwards it on to the selected provider? Great!

But that seems to not be the case?

Resulting in a horrendously large Jar with so much third party code I really dont want.

Why is it that the other libs seem to just talk to your server and the android one uses providers?

Library is triggering GPS

If the app has the location permission, the Segment.io library seems to be triggering the GPS hardware on launch.

From our research, it seems to be coming from here:

infoManager = new InfoManager();

The InfoManager tries to get a general location, and if the hardware doesn't have a good enough lock it may decide to start the GPS.

We're not using any location data in our analytics, is there a way we can configure the library to not do this? We've been getting complaints from our users saying the app is using location when they aren't using the map functionality of the app.

Mixpanel Screen API

I was banging my head as to why Analytics.screen would not send any thing to Mixpanel thinking I was doing something wrong but then I read this in Mixpanel integration...

if (isMixpanelPeopleEnabled()) {
  // consider the charge
  if (properties != null && properties.has("revenue")) {
    MixpanelAPI.People people = mixpanel.getPeople();
    double revenue = properties.getDouble("revenue", 0.0);
    people.trackCharge(revenue, properties);
  }
}

Why does it only send screen view for revenue?!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.