Ответ 1
Проблема с вызовом start()/stop() в каждом действии (по предложению Кристиана) заключается в том, что она приводит к новому "посещению" для каждого действия, к которому ведет ваш пользователь. Если это подходит для вашего использования, то это прекрасно, однако, это не так, как большинство людей ожидают, что посещения будут работать. Например, это очень затрудняет сравнение номеров Android с номерами в Интернете или iphone, поскольку "посещение" в Интернете и iphone сопоставляется с сеансом, а не с страницей/активностью.
Проблема с вызовом start()/stop() в вашем приложении заключается в том, что он приводит к неожиданно продолжительным посещениям, поскольку Android не дает никаких гарантий для прекращения действия приложения после закрытия последнего действия. Кроме того, если ваше приложение ничего не делает с уведомлениями или услугами, эти фоновые задачи могут запускать ваше приложение и приводить к посещениям "phantom". UPDATE: stefano правильно указывает, что onTerminate() никогда не вызывается на реальном устройстве, поэтому нет очевидного места для остановки вызова().
Проблема с вызовом start()/stop() в одном "основном" действии (как это было предложено Aurora) заключается в том, что нет гарантии, что активность будет действовать в течение всего времени, которое ваш пользователь использует для вашего приложения. Если "основная" активность уничтожается (скажем, чтобы освободить память), ваши последующие попытки записать события в GA в других действиях будут терпеть неудачу, потому что сеанс остановлен.
Кроме того, есть ошибка в Google Analytics, по крайней мере, с версией 1.2, которая заставляет его поддерживать сильную ссылку на контекст, который вы передаете, чтобы начать(), не позволяя ему получать мусор, собранный после его уничтожения. В зависимости от размера вашего контекста это может быть значительная утечка памяти.
Утечка памяти достаточно проста для исправления, ее можно решить, вызвав start(), используя приложение, а не сам экземпляр активности. docs, вероятно, должен быть обновлен, чтобы отразить это.
например. изнутри вашей деятельности:
// 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(), когда счетчик достигнет нуля.
Новая библиотека EasyTracker от Google позаботится об этом для вас.
В качестве альтернативы, если вы не можете подклассифицировать действия 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;
}
}