web-dev-qa-db-ja.com

AndroidアプリでのGoogleアナリティクス-複数のアクティビティの処理

アプリでGoogleアナリティクスを設定するのがいかに簡単であるかを知ってとても興奮しましたが、ドキュメントがないため、いくつか質問があります。私が見つけることができる唯一の情報は、ドキュメント here からのものです。これは、1つのアクティビティからのページビューとイベントのレポートのみを確認します。アプリの複数のアクティビティのページビューとイベントを報告したいのですが。

現在、すべてのアクティビティのonCreate()で、次のように呼び出しています。

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

そして、私のすべての活動のonDestroy()で:

    tracker.stop();

次に、必要に応じてPageViewsとイベントを追跡し、実行している別のHTTPリクエストとともにそれらをディスパッチします。しかし、これが最善の方法であるかどうかはわかりません。各アクティビティでstart()とstop()を呼び出す必要がありますか、それともメインのランチャーアクティビティでのみstart()とstop()を呼び出す必要がありますか?

45
Aurora

(Christianによって提案されたように)すべてのアクティビティでstart()/ stop()を呼び出すことの問題は、ユーザーがナビゲートするすべてのアクティビティに対して新しい「訪問」が発生することです。これがあなたの使用に問題がなければ、それは問題ありませんが、ほとんどの人が訪問が機能することを期待する方法ではありません。たとえば、これはAndroid番号をWebまたはiphone番号と比較することを非常に困難にします。これは、Webおよびiphone上の「訪問」がページ/アクティビティではなくセッションにマッピングされるためです。

Androidは、最後のアクティビティが閉じた後にアプリケーションを終了することを保証しないため、アプリケーションでstart()/ stop()を呼び出すことの問題は、予想外に長い訪問につながることです。さらに、アプリが通知やサービスを使用して何かを行うと、これらのバックグラウンドタスクがアプリを起動し、「ファントム」なアクセスにつながる可能性があります。UPDATE:stefanoは、 onTerminate( ) が実際のデバイスで呼び出されることはないため、stop()への呼び出しを配置する明確な場所はありません。

1つの「メイン」アクティビティ(Auroraで推奨)でstart()/ stop()を呼び出す場合の問題は、ユーザーがアプリを使用している間、アクティビティが継続する保証がないことです。 「メイン」アクティビティが破棄された場合(メモリを解放するためなど)、他のアクティビティでGA)にイベントを書き込む後続の試行は、セッションが停止しているため失敗します。

さらに、Googleアナリティクスには少なくともバージョン1.2までのバグがあり、start()に渡したコンテキストへの強い参照を維持するため、破壊後にガベージコレクションが行われません。コンテキストのサイズによっては、かなりのメモリリークになる可能性があります。

メモリリークは簡単に修正できます。アクティビティインスタンス自体の代わりにアプリケーションを使用して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;
    }
}
79
emmby

SDKには、これをすべて処理する外部ライブラリがあります。その呼ばれるEasyTracker。それをインポートして、提供されたActivityまたはListActivityを拡張し、コードで文字列リソースを作成すれば完了です。

17
sfratini

トラッカーは、それが実行されたアクティビティのみを追跡します。では、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
    }
}
5
Cristian

私が使用しているアプローチは、バインドされたサービスを使用することです(私はすでに使用しているため、追加のボイラープレートコードの作成を免れました)。

バインドされたサービスは、それにバインドされたアクティビティがある限りのみ持続します。アプリ内のすべてのアクティビティはこのサービスにバインドされるため、ユーザーがアプリをアクティブに使用している間のみ継続します。つまり、実際の「セッション」になります。

拡張した静的インスタンスgetInstance()を追加したApplicationのシングルトンインスタンスでトラッカーを開始し、インスタンスを取得します。

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

1
evaneus

私のアプリでは、訪問間で時間ベースの分割を行い、次のように動作しました:

私はGoogleAnalyticsTrackerのラッパーシングルトントラッカーオブジェクトを構築しました。その時間がx秒以上の場合、私はそれを新しい訪問として扱います。

もちろん、これはアプリ内のすべてを追跡する場合にのみ役立ちますが、すべての状況で最適なソリューションとは限りませんが、私のアプリではうまく機能します。

TrackPageViewのみをサポートしますが、setCustomVarとtrackEventは簡単に実装できます。

何かを追跡する必要がある場所はどこでも、次の行を追加するだけです。

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

通常はアクティビティのonResumeで行います

トラッカー要旨

1
fasmide

次のようなものが必要になります: http://mufumbo.wordpress.com/2011/06/13/google-analytics-lags-on-Android-how-to-make-it-sensitive/

これは以前のバージョンにあり、非常によく機能していました。今、私はあなたと同じ苦労をしています。V2は非常に一貫性がないようです。

1
Rafael Sanches

これは、AOPを使用して実行できるものなのでしょうか。

Androidはコンパイル時のAOPメソッドしか使用できないため、AspectJのようなものでしょうか?

Android in this thread )にAspectJの使用に関するもう少し詳しい情報があります。主な問題は、自分が所有するクラスで宣言する必要があることです。

0
Ben Neill