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

Aur*_*ora 45 android google-analytics

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

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

    tracker = GoogleAnalyticsTracker.getInstance();
    tracker.start("UA-xxxxxxxxx", this);
Run Code Online (Sandbox Code Playgroud)

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

    tracker.stop();
Run Code Online (Sandbox Code Playgroud)

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

emm*_*mby 79

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

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

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

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

内存泄漏很容易修复,可以通过使用Application而不是activity实例本身调用start()来解决.该文档或许应该更新,以反映这一点.

例如.来自您的活动:

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

代替

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

关于何时调用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于遇到此问题的其他人 - 上述解决方案效果非常好,但是GoogleAnalyticsTracker`的`start`和`stop`方法都被弃用(Eclipse会抛出警告) - 只需替换为`startNewSession`和`stopSession`分别是`GoogleAnalyticsSessionManager.incrementActivityCount`. (5认同)
  • 如果用户总是一直回到关闭应用程序,您的引用计数解决方案就可以正常工作.然而,它的背景和回归它仍然算作一次访问.如果你想跟踪这两个单独的访问(我做过),你可以利用这样一个事实:当A-> BB时,在A的onStop之前调用onResume.因此,在onResume中递增计数器,在onStop中递减.当计数器为0时,您的应用程序将不再可见. (4认同)
  • 是的,阅读该帖子让我完成并完全重写我在我的应用程序中使用Google AnalyticsAPi的方式.荣幸,虽然我暗中憎恨你破坏我的​​人工访问计数泡沫. (2认同)

sfr*_*ini 17

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


Cri*_*ian 5

跟踪器仅跟踪执行它的活动.那么,为什么不将每次启动它的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
}
Run Code Online (Sandbox Code Playgroud)

然后,您为所使用的每个活动扩展该类:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 现在时间过去了,我可以在Google Analytics中看到结果.我只在我的主要活动中调用start()和stop().每次启动应用程序都代表一次"访问".如果您想在每个活动上进行独特的"访问",那么Cristian C.提供的解决方案可能会有效. (3认同)