Android应用中的Google Analytics - 处理多项活动

时间:2010-07-09 21:30:04

标签: android google-analytics

我很高兴看到使用我的应用程序设置Google Analytics是多么容易,但缺少文档让我有几个问题。我能找到的唯一信息就是文档here,它只关注从一个Activity报告PageViews和Events。我想在我的应用程序中跨多个活动报告PageViews和事件。

现在,在我所有活动的onCreate()中,我打电话给:

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

在我所有活动的onDestroy()中:

    tracker.stop();

然后我根据需要跟踪PageViews和事件,并将它们与我正在执行的另一个HTTP请求一起发送。但我不太确定这是最好的方法。我应该在每个活动中调用start()和stop(),还是应该只在主启动器活动中调用start()和stop()?

7 个答案:

答案 0 :(得分:79)

在每个活动中调用start()/ stop()的问题(如Christian所建议的)是,它会导致用户导航到的每个活动都有一个新的“访问”。如果这对您的使用没有问题,那么这很好,但是,这并不是大多数人期望访问工作的方式。例如,这会使得Android号码与网络或iPhone号码的比较非常困难,因为网络上的“访问”和iphone映射到会话,而不是页面/活动。

在您的应用程序中调用start()/ stop()的问题是它会导致意外长时间访问,因为Android不保证在您上次活动关闭后终止应用程序。此外,如果您的应用对通知或服务执行任何操作,这些后台任务可以启动您的应用并导致“幻影”访问。 更新:stefano正确指出onTerminate()永远不会在真实设备上调用,因此没有明显的地方可以将调用置于停止()。

在单个“主”活动中调用start()/ stop()的问题(如Aurora所建议的)是,无法保证活动会在用户使用您的应用程序期间保持活动状态。如果“主”活动被销毁(比如释放内存),那么随后尝试在其他活动中向GA写入事件将会失败,因为会话已经停止。

此外,至少版本1.2中的Google Analytics中存在一个错误,导致它对您传递给start()的上下文保持强引用,从而防止它在被破坏后被垃圾收集。根据您的上下文的大小,这可能是一个相当大的内存泄漏。

内存泄漏很容易修复,可以通过使用Application而不是activity实例本身调用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 ()当计数达到零时。

来自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;
    }
}

答案 1 :(得分:17)

SDK现在有一个外部库来处理所有这些。它叫做EasyTracker。您只需导入它并扩展提供的Activity或ListActivity,使用您的代码创建字符串资源即可完成。

答案 2 :(得分:5)

跟踪器只会跟踪执行它的活动。那么,为什么不对每次在onCreate上启动它的Activity进行子类化:

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
    }
}

答案 3 :(得分:1)

我使用的方法是使用绑定服务(我恰好使用了一个绑定服务,因此可以节省额外的锅炉板代码的创建。)

绑定服务只会在绑定了活动时才会持续。我的应用程序中的所有活动都绑定到此服务,因此只要用户正在使用我的应用程序,它就会持续 - 因此非常真实的“会话”。

我使用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

答案 4 :(得分:1)

我在我的应用中进行了基于时间的分割,工作方式如下:

我为GoogleAnalyticsTracker构建了一个包装器单件跟踪器对象,我保留了最后一次跟踪的内容。如果那个时间超过x秒我将其视为新访问。

当然,这只有在您跟踪应用中的所有内容时才有用,并且在某些情况下可能不是最佳解决方案,但对我的应用效果很好。

它只支持trackPageView,但是应该可以轻松实现setCustomVar和trackEvent。

您需要跟踪某些内容的任何地方只需添加以下行:

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

我通常在活动的onResume中执行此操作

Tracker gist

答案 5 :(得分:1)

你需要这样的东西:http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-android-how-to-make-it-responsive/

这是以前的版本并且过去非常好用。现在我和你一样挣扎,因为V2似乎不是很一致。

答案 6 :(得分:0)

我想知道这是否可以使用AOP完成。

Android只能使用编译时AOP方法,所以可能像AspectJ?

this thread中有关于在Android中使用AspectJ的更多信息。主要问题是您仍然需要在您拥有的类上声明。