Google Analytics в приложении Android - работа с несколькими видами деятельности - PullRequest
45 голосов
/ 10 июля 2010

Я был очень взволнован, увидев, как легко настроить Google Analytics с моим приложением, но отсутствие документации заставляет меня задаться несколькими вопросами.Единственная информация, которую я могу найти, - это прямо из документации здесь , которая рассматривает только отчеты о просмотрах страниц и событиях из одного действия.Я хочу сообщить о просмотрах страниц и событиях по нескольким действиям в моем приложении.

Прямо сейчас в onCreate () всех моих действий я звоню:

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

И в onDestroy() всех моих действий:

    tracker.stop();

Затем я отслеживаю PageViews и события по мере необходимости и отправляю их вместе с другим HTTP-запросом, который я выполняю.Но я не уверен, что это лучший способ.Должен ли я вызывать start () и stop () в каждом действии, или я должен вызывать только start () и stop () в своем основном действии средства запуска?

Ответы [ 7 ]

79 голосов
/ 06 июня 2011

Проблема с вызовом start () / stop () в каждом действии (как предполагает Кристиан) заключается в том, что это приводит к новому «посещению» для каждого действия, к которому переходит ваш пользователь. Если это нормально для вашего использования, тогда это нормально, однако большинство людей не ожидают, что посещения будут работать. Например, это очень затруднит сравнение номеров андроидов с номерами в сети или iphone, поскольку «посещение» в Интернете и iphone сопоставляет сеанс, а не страницу / действие.

Проблема с вызовом start () / stop () в вашем Приложении заключается в том, что это приводит к неожиданно долгим посещениям, поскольку Android не гарантирует прекращение работы приложения после закрытия вашего последнего действия. Кроме того, если ваше приложение выполняет какие-либо действия с уведомлениями или службами, эти фоновые задачи могут запустить ваше приложение и привести к "фантомным" посещениям. ОБНОВЛЕНИЕ: Стефано правильно указывает на то, что onTerminate () никогда не вызывается на реальном устройстве, поэтому нет очевидного места для вызова stop ().

Проблема с вызовом start () / stop () в одном «основном» действии (как предполагает Aurora) заключается в том, что нет гарантии, что это задание будет сохраняться в течение всего времени использования вашего приложения вашим пользователем. Если «основное» действие уничтожено (скажем, для освобождения памяти), ваши последующие попытки записать события в GA в других действиях потерпят неудачу, поскольку сеанс был остановлен.

Кроме того, в Google Analytics есть ошибка, по крайней мере, до версии 1.2, из-за которой она сохраняет четкую ссылку на контекст, который вы передаете в start (), не позволяя собирать мусор после его уничтожения. В зависимости от размера вашего контекста, это может быть значительная утечка памяти.

Утечка памяти достаточно легко исправить, ее можно устранить, вызвав start (), используя приложение вместо самого экземпляра действия. документы , вероятно, следует обновить, чтобы отразить это.

например. из вашей деятельности:

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

вместо

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

Относительно того, когда вызывать start () / stop (), вы можете реализовать своего рода ручной подсчет ссылок, увеличивая счетчик для каждого вызова Activity.onCreate () и уменьшая для каждого onDestroy (), затем вызывая GoogleAnalyticsTracker.stop () когда счет достигает нуля.

Новая библиотека от Google EasyTracker позаботится об этом за вас.

В качестве альтернативы, если вы не можете создать подкласс действий EasyTracker, вы можете самостоятельно реализовать это вручную в своем собственном базовом классе действий:

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;
    }
}
17 голосов
/ 03 января 2012

SDK теперь имеет внешнюю библиотеку, которая позаботится обо всем этом. Это называется EasyTracker. Вы можете просто импортировать его и расширить предоставленный Activity или ListActivity, создать строковый ресурс с вашим кодом, и все готово.

5 голосов
/ 10 июля 2010

Трекер будет отслеживать только ту деятельность, в которой он выполняется.Итак, почему бы вам не создать подкласс Activity, который запускает ее каждый раз на 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
}

Затем вы расширяете этот класс для каждого используемого вами действия:

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
    }
}
1 голос
/ 08 марта 2013

Вам понадобится что-то вроде этого: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-android-how-to-make-it-responsive/

Это на предыдущей версии и раньше работал очень хорошо. Сейчас я в той же борьбе, что и вы, потому что V2 не очень последовательный.

1 голос
/ 27 сентября 2011

Я сделал временное разделение между посещениями в моем приложении, работая так:

Я создал объект-обертку-одиночка Tracker для GoogleAnalyticsTracker, где я храню последний раз, когда что-то отслеживалось. Если это время превышает x секунд, я считаю его новым посещением.

Конечно, это полезно только в том случае, если вы отслеживаете все в своем приложении, и, возможно, не является лучшим решением в любой ситуации, однако хорошо работает для моего приложения.

Он поддерживает только trackPageView, но setCustomVar и trackEvent должны быть легко реализованы.

Везде, где вам нужно что-то отслеживать, просто добавьте строку:

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

Обычно я делаю это в резюме деятельности

Трек отслеживания

1 голос
/ 14 сентября 2011

Подход, который я использую, заключается в использовании Bound Service (я использую его уже, так что избавлен от создания дополнительного кода котельной плиты.)

Связанная служба будет действовать только до тех пор, пока с ней связаны действия. Все действия в моем приложении связаны с этим сервисом, поэтому он длится только до тех пор, пока пользователь активно использует мое приложение, поэтому это настоящая «сессия».

Я запускаю трекер с единичным экземпляром Application, который я расширил, и добавил статический метод getInstance () для получения экземпляра:

// 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();
}

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

0 голосов
/ 16 августа 2012

Интересно, можно ли это сделать с помощью AOP.

Android может использовать только методы AOP во время компиляции, так что может быть что-то вроде AspectJ?

Есть немного больше информации об использованииAspectJ в Android в этой теме .Основная проблема заключается в том, что вам все равно нужно объявлять классы, которыми вы владеете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...