Google Analytics в приложении для Android – работа с несколькими действиями

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

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

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

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

  tracker.stop(); 

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

Solutions Collecting From Web of "Google Analytics в приложении для Android – работа с несколькими действиями"

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

Проблема с вызовом start () / stop () в вашем приложении заключается в том, что он приводит к неожиданно продолжительным посещениям, поскольку Android не дает никаких гарантий для прекращения действия приложения после закрытия последнего действия. Кроме того, если ваше приложение ничего не делает с уведомлениями или услугами, эти фоновые задачи могут запускать ваше приложение и приводить к «фантомным» посещениям. UPDATE: stefano правильно указывает, что onTerminate () никогда не вызывается на реальном устройстве, поэтому нет очевидного места для остановки вызова ().

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

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

Утечка памяти достаточно проста для исправления, ее можно решить, вызвав 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 (), когда Счетчик достигает нуля.

Новая библиотека 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; } } 

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

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

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

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

Я запускаю трекер с экземпляром Singleton приложения, который я расширил, и добавил статический метод 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.

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

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

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

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

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

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

Обычно я делаю это в onResume активности

Отслеживание

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

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

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

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

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