Google Analytics w aplikacji na Androida-radzenie sobie z wieloma działaniami

Byłem bardzo podekscytowany, widząc, jak łatwo jest skonfigurować Google Analytics z moją aplikacją, ale brak dokumentacji sprawia, że siedzę z kilkoma pytaniami. Jedyne informacje, które mogę znaleźć, pochodzą z dokumentacji TUTAJ , która dotyczy tylko raportowania przeglądów stron i zdarzeń z jednego działania. Chcę zgłaszać wyświetlenia stron i wydarzenia z wielu działań w mojej aplikacji.

W tej chwili w onCreate() wszystkich moich działań, dzwonię:

    tracker = GoogleAnalyticsTracker.getInstance();
    tracker.start("UA-xxxxxxxxx", this);

I w onDestroy () wszystkich moich działań:

    tracker.stop();

Następnie śledzę przeglądy stron i zdarzenia w razie potrzeby i wysyłam je wraz z innym żądaniem HTTP, które wykonuję. Ale nie jestem pewien, czy to najlepszy sposób. Czy powinienem wywoływać start() i stop() w każdej aktywności, czy powinienem wywoływać start() i stop () tylko w mojej głównej aktywności uruchamiającej?

Author: Aurora, 2010-07-10

7 answers

Problem z wywołaniem start () / stop () w każdej aktywności (zgodnie z sugestią Christiana) polega na tym, że powoduje to nową "wizytę" dla każdej aktywności, do której przechodzi użytkownik. Jeśli jest to w porządku, to jest w porządku, jednak nie jest to sposób, w jaki większość ludzi oczekuje wizyt w pracy. Na przykład porównanie numerów Androida z numerami sieciowymi lub iphone ' a byłoby bardzo trudne, ponieważ "wizyta" w Internecie i iphone mapuje sesję, a nie Stronę/aktywność.

Problem z wywołaniem start () / stop () w aplikacji polega na tym, że powoduje nieoczekiwanie długie wizyty, ponieważ Android nie gwarantuje zakończenia aplikacji po zamknięciu ostatniej aktywności. Ponadto, jeśli aplikacja robi cokolwiek z powiadomieniami lub usługami, te zadania w tle mogą uruchomić aplikację i spowodować wizyty "fantomowe". UPDATE: stefano prawidłowo zaznacza, że onTerminate () nigdy nie jest wywoływane na prawdziwym urządzeniu, więc nie ma oczywistego miejsca, w którym można umieścić wywołanie stop().

Problem z wywołaniem start () / stop () w pojedynczej "głównej" aktywności (jak sugeruje Aurora) polega na tym, że nie ma gwarancji, że aktywność pozostanie na czas, przez który użytkownik korzysta z aplikacji. Jeśli aktywność "główna" zostanie zniszczona (np. aby zwolnić pamięć), kolejne próby zapisu zdarzeń do GA w innych aktywnościach zakończą się niepowodzeniem, ponieważ sesja została zatrzymana.

Dodatkowo jest błąd w Google Analytics w co najmniej wersji 1.2 to powoduje, że zachowuje silne odniesienie do kontekstu, który przekazujesz startowi (), zapobiegając zbieraniu śmieci po jego zniszczeniu. W zależności od rozmiaru kontekstu może to być spory wyciek pamięci.

Wyciek pamięci jest wystarczająco łatwy do naprawienia, można go rozwiązać poprzez wywołanie start() przy użyciu aplikacji zamiast samej instancji activity. dokumenty powinny być prawdopodobnie zaktualizowane, aby to odzwierciedlić.

Np. z wnętrza Twojej aktywności:

// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", getApplication() );

Zamiast

// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", this ); // BAD

Jeśli chodzi o czas wywołania start () / stop (), można zaimplementować rodzaj ręcznego zliczania referencji, zwiększając liczbę dla każdego wywołania do aktywności.onCreate () i decrementing dla każdego ondestroy (), a następnie wywołanie GoogleAnalyticsTracker.stop() gdy liczba osiągnie zero.

Nowa Biblioteka EasyTracker od Google zajmie się tym za Ciebie.

Alternatywnie, jeśli nie możesz podklasować działań EasyTracker, możesz zaimplementować to ręcznie we własnej klasie bazowej activity:

public abstract class GoogleAnalyticsActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Need to do this for every activity that uses google analytics
        GoogleAnalyticsSessionManager.getInstance(getApplication()).incrementActivityCount();
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Example of how to track a pageview event
        GoogleAnalyticsTracker.getInstance().trackPageView(getClass().getSimpleName());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // Purge analytics so they don't hold references to this activity
        GoogleAnalyticsTracker.getInstance().dispatch();

        // Need to do this for every activity that uses google analytics
        GoogleAnalyticsSessionManager.getInstance().decrementActivityCount();
    }

}



public class GoogleAnalyticsSessionManager {
    protected static GoogleAnalyticsSessionManager INSTANCE;

    protected int activityCount = 0;
    protected Integer dispatchIntervalSecs;
    protected String apiKey;
    protected Context context;

    /**
     * NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks.
     */
    protected GoogleAnalyticsSessionManager( String apiKey, Application context ) {
        this.apiKey = apiKey;
        this.context = context;
    }

    /**
     * NOTE: you should use your Application context, not your Activity context, in order to avoid memory leaks.
     */
    protected GoogleAnalyticsSessionManager( String apiKey, int dispatchIntervalSecs, Application context ) {
        this.apiKey = apiKey;
        this.dispatchIntervalSecs = dispatchIntervalSecs;
        this.context = context;
    }

    /**
     * This should be called once in onCreate() for each of your activities that use GoogleAnalytics.
     * These methods are not synchronized and don't generally need to be, so if you want to do anything
     * unusual you should synchronize them yourself.
     */
    public void incrementActivityCount() {
        if( activityCount==0 )
            if( dispatchIntervalSecs==null )
                GoogleAnalyticsTracker.getInstance().start(apiKey,context);
            else
                GoogleAnalyticsTracker.getInstance().start(apiKey,dispatchIntervalSecs,context);

        ++activityCount;
    }


    /**
     * This should be called once in onDestrkg() for each of your activities that use GoogleAnalytics.
     * These methods are not synchronized and don't generally need to be, so if you want to do anything
     * unusual you should synchronize them yourself.
     */
    public void decrementActivityCount() {
        activityCount = Math.max(activityCount-1, 0);

        if( activityCount==0 )
            GoogleAnalyticsTracker.getInstance().stop();
    }


    /**
     * Get or create an instance of GoogleAnalyticsSessionManager
     */
    public static GoogleAnalyticsSessionManager getInstance( Application application ) {
        if( INSTANCE == null )
            INSTANCE = new GoogleAnalyticsSessionManager( ... ,application);
        return INSTANCE;
    }

    /**
     * Only call this if you're sure an instance has been previously created using #getInstance(Application)
     */
    public static GoogleAnalyticsSessionManager getInstance() {
        return INSTANCE;
    }
}
 78
Author: emmby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-23 20:58:48

SDK ma teraz zewnętrzną bibliotekę, która zajmuje się tym wszystkim. Nazywa się EasyTracker. Możesz po prostu zaimportować go i rozszerzyć podaną aktywność lub aktywność listową, utworzyć zasób ciągów z kodem i gotowe.

 17
Author: sfratini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-02 23:24:53

Tracker będzie śledzić aktywność tylko tam, gdzie jest wykonywana. Więc dlaczego nie podklasujesz aktywności, która uruchamia ją za każdym razem na onCreate:

public class GAnalyticsActivity extends Activity{

    public void onCreate(Bundle icicle){
        super.onCreate(icile);
        tracker = GoogleAnalyticsTracker.getInstance();
        tracker.start("UA-xxxxxxxxx", this);
    }

    // same for on destroy
}

Następnie rozszerzasz tę klasę dla każdej aktywności, której używasz:

public class YourActivity extends GAnalyticsActivity{
    public void onCreate(Bundle icicle){
        super.onCreate(icile);
        // whatever you do here you can be sure 
        // that the tracker has already been started
    }
}
 5
Author: Cristian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-09 21:39:10

Podejście, którego używam, polega na korzystaniu z usługi związanej (tak się składa, że używam już jednej, więc oszczędzono na tworzeniu dodatkowego kodu płyty kotła.)

Usługa związana będzie działać tylko tak długo, jak długo będą z nią związane czynności. Wszystkie działania w mojej aplikacji wiążą się z tą usługą, więc trwa ona tylko tak długo, jak użytkownik aktywnie korzysta z mojej aplikacji - a więc bardzo realna "sesja".

Uruchamiam Trackera z pojedynczą instancją aplikacji, którą rozszerzyłem i dodałem statyczna metoda getInstance () do pobrania instancji:

// Non-relevant code removed

public IBinder onBind(Intent intent) {
    tracker = GoogleAnalyticsTracker.getInstance();
    tracker.startNewSession(PROPERTY_ID, MyApp.getInstance());
}


public boolean onUnbind(Intent intent) {
    tracker.stopSession();
}

Zobacz: http://developer.android.com/guide/topics/fundamentals/bound-services.html

 1
Author: evaneus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-14 18:56:39

Zrobiłem Podział czasu między odwiedzinami w mojej aplikacji, działa tak:

Zbudowałem obiekt wrapper singleton Tracker dla GoogleAnalyticsTracker, gdzie trzymałem ostatnio coś śledzonego. Jeśli ten czas jest większy niż X sekund traktuję to jako nową wizytę.

Oczywiście jest to przydatne tylko wtedy, gdy śledzisz wszystko w swojej aplikacji i może nie być najlepszym rozwiązaniem w każdej sytuacji, ale działa dobrze dla mojej aplikacji.

Obsługuje tylko trackPageView, ale setCustomVar trackEvent powinien być łatwo zaimplementowany..

Gdziekolwiek chcesz coś śledzić po prostu dodaj linię:

    Tracker.getInstance(getApplicationContext()).trackPageView("/HelloPage");

Zwykle robię to w onResume aktywności

Tracker gist

 1
Author: fasmide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-27 00:26:15

Będziesz potrzebował czegoś takiego: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-android-how-to-make-it-responsive/

To jest na poprzedniej wersji i działa bardzo dobrze. Teraz jestem w tej samej walce co ty, ponieważ V2 nie wydaje się być zbyt konsekwentny.

 1
Author: Rafael Sanches,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-06 17:29:58

Zastanawiam się, czy to jest coś, co można zrobić za pomocą AOP.

Android może używać tylko metod kompilacji AOP więc może coś w stylu AspectJ?

Więcej informacji na temat używania AspectJ w Androidzie znajdziesz w w tym wątku. Głównym problemem jest to, że nadal będziesz musiał zadeklarować na klasach, które posiadasz.
 0
Author: Ben Neill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:02