J'étais assez enthousiaste à l'idée de voir à quel point il est facile de configurer Google Analytics avec mon application, mais le manque de documentation m'oblige à poser quelques questions. La seule information que je puisse trouver provient de la documentation here , qui ne traite que du rapport sur les vues de page et les événements d'une activité. Je souhaite signaler des vues de page et des événements sur plusieurs activités dans mon application.
En ce moment dans le onCreate () de toutes mes activités, j'appelle:
tracker = GoogleAnalyticsTracker.getInstance();
tracker.start("UA-xxxxxxxxx", this);
Et dans le onDestroy () de toutes mes activités:
tracker.stop();
Je surveille ensuite les vues de page et les événements selon les besoins, puis les envoie avec une autre requête HTTP que je suis en train d'exécuter. Mais je ne suis pas sûr que ce soit le meilleur moyen. Devrais-je appeler start () et stop () dans chaque activité, ou devrais-je uniquement appeler start () et stop () dans mon activité principale de lancement?
Le problème avec l'appel de start ()/stop () dans chaque activité (comme suggéré par Christian) est qu'il en résulte une nouvelle "visite" pour chaque activité à laquelle votre utilisateur accède. Si cela vous convient, alors tout va bien, mais ce n'est pas ainsi que la plupart des gens s'attendent à ce que les visites fonctionnent. Par exemple, cela rendrait très difficile la comparaison de numéros Android avec des numéros Web ou iPhone, puisqu’une "visite" sur le Web et sur un iPhone correspond à une session, et non à une page/activité.
Le problème avec l'appel de start ()/stop () dans votre application est qu'il en résulte des visites inattendues, car Android ne garantit pas la fermeture de l'application après la fermeture de votre dernière activité. En outre, si votre application utilise des notifications ou des services, ces tâches en arrière-plan peuvent démarrer votre application et générer des visites "fantômes". UPDATE: stefano indique à juste titre que onTerminate () n'est jamais appelé sur un périphérique réel. Il n'y a donc aucun endroit évident où mettre l'appel à stop ().
Le problème avec l'appel de start ()/stop () dans une seule activité "principale" (comme suggéré par Aurora) est qu'il n'y a aucune garantie que l'activité restera en place pendant la durée d'utilisation de votre application par l'utilisateur. Si l'activité "principale" est détruite (par exemple pour libérer de la mémoire), vos tentatives ultérieures d'écriture d'événements sur GA dans d'autres activités échoueront, car la session a été arrêtée.
De plus, dans la version 1.2 au moins, Google Analytics a rencontré un bogue qui lui permettait de conserver une référence forte au contexte que vous transmettiez à start (), l'empêchant ainsi de récupérer des déchets après leur destruction. Selon la taille de votre contexte, cela peut constituer une fuite de mémoire importante.
La fuite de mémoire est assez facile à corriger, elle peut être résolue en appelant start () à l'aide de l'application au lieu de l'instance d'activité elle-même. Les docs devraient probablement être mis à jour pour refléter cela.
par exemple. de l'intérieur de votre activité:
// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", getApplication() );
au lieu de
// Start the tracker in manual dispatch mode...
tracker.start("UA-YOUR-ACCOUNT-HERE", this ); // BAD
Concernant le moment d'appeler start ()/stop (), vous pouvez implémenter une sorte de comptage manuel des références, incrémenter un décompte pour chaque appel à Activity.onCreate () et décrémenter pour chaque onDestroy (), puis appeler GoogleAnalyticsTracker.stop () lorsque le compte atteint zéro.
La nouvelle bibliothèque EasyTracker de Google s'occupera de cela pour vous.
Si vous ne pouvez pas sous-classer les activités EasyTracker, vous pouvez également l'implémenter manuellement vous-même dans votre propre classe de base d'activités:
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;
}
}
Le SDK a maintenant une bibliothèque externe qui s'occupe de tout cela. C'est ce qu'on appelle EasyTracker. Vous pouvez simplement l'importer et étendre l'activité ou la liste fournie, créer une ressource de chaîne avec votre code et vous avez terminé.
Le suivi ne suivra que l'activité où il est exécuté. Alors, pourquoi ne pas sous-classer une activité qui la lance à chaque fois sur 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
}
Ensuite, vous étendez cette classe pour chaque activité que vous utilisez:
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
}
}
L’approche que j’utilise consiste à utiliser un service lié (j’en utilise déjà un, j’ai donc été épargnée par la création d’un code de plaque supplémentaire pour la chaudière.)
Un service lié ne durera que tant qu'il y aura des activités liées. Toutes les activités de mon application sont liées à ce service, il ne dure donc que tant que l'utilisateur utilise activement mon application - il s'agit donc bien d'une véritable "session".
Je lance le suivi avec une instance singleton d'Application que j'ai étendue et j'ai ajouté une méthode statique getInstance () pour récupérer l'instance:
// 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();
}
Voir: http://developer.Android.com/guide/topics/fundamentals/bound-services.html
J'ai effectué une répartition dans le temps entre les visites de mon application, en procédant comme suit:
J'ai construit un objet Tracker Singleton pour GoogleAnalyticsTracker où je garde la dernière fois que quelque chose a été suivi. Si ce temps est plus que x secondes, je le traite comme une nouvelle visite.
Bien sûr, cela n’est utile que si vous suivez tout dans votre application, et peut ne pas être la meilleure solution dans toutes les situations, mais cela fonctionne bien pour mon application.
Il ne supporte que trackPageView, mais setCustomVar et trackEvent devraient être facilement implémentés.
N'importe où vous devez suivre quelque chose, ajoutez simplement la ligne:
Tracker.getInstance(getApplicationContext()).trackPageView("/HelloPage");
Je le fais habituellement dans le résumé d'une activité
Vous aurez besoin de quelque chose comme ceci: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-Android-how-to-make-it-responsive/
C'est sur la version précédente et fonctionnait très bien. Maintenant, je suis dans la même lutte que vous, car la V2 ne semble pas très cohérente.
Je me demande si cela pourrait être fait avec AOP.
Android ne peut utiliser que les méthodes AOP au moment de la compilation, alors peut-être quelque chose comme AspectJ?
Il y a un peu plus d'informations sur l'utilisation de AspectJ dans Android dans ce fil . Le problème principal étant que vous auriez encore besoin de déclarer vos classes.