计算会话长度android

时间:2016-03-27 06:58:16

标签: android android-notifications

如何在Android中计算用户的会话长度,以便我可以在合适的时间推送广告?有没有可以帮助我的图书馆。我使用谷歌分析来获得平均会话长度,但我如何获得个人用户?

3 个答案:

答案 0 :(得分:4)

我发现了同样的问题并对这个问题进行了一些研究。 我的结论是:

定义用户会话是一件非常复杂的事情。

  • "您打开的(第三方)电子邮件应用是否可以编写应用和会话的反馈部分?"。这同样适用于任何共享应用或任何播放器。

  • 当用户切换回另一个应用以检查其他应用上的内容并返回时,是应用会话的那一部分。请注意,我不是在谈论前一种情况,我的意思是用户使用菜单/桌面/应用列表按钮进行切换。

  • 当设备在一段时间后进入睡眠模式时,您的会话计时器是否会继续计数?当用户唤醒他的设备时,您的应用仍将处于前台。

我还发现了一些Android特定问题:

  • Android没有应用程序会话长度的本机概念。也就是说,用户在前台花了多少时间。

  • Android应用程序实际上是一系列屏幕(活动)。

  • Android有一个Application类,但它不是开发人员如何以及何时创建/杀死它。这是一项操作系统任务。您的应用可能在后台,但您的应用类仍然可以在内存中。

  • 有些方法不值得依赖它们,比如Activity.OnStop(参见http://developer.android.com/intl/es/reference/android/app/Activity.html#onStop()

所以我的最终解决方案是:

在Application上添加一个计时器(实际上是一个很简单的指向System.currentTimeMillis() 添加"打开"活动计数器,在Application.onCreate()

上初始化为0

向Application添加onActivityResumed()方法。如果前一个计数器值为0,我应该递增计数器并初始化计时器。 添加到所有活动onResume()调用Application.onActivityResumed()

向Application添加onActivityPaused()方法。它递减计数器并触发超时任务(定义如下) 在所有Activities.onPause()

上添加对Application.onActivityPaused()的调用

当计数器达到0时,我们不能理所当然地认为会话已经完成,我们可能只是从我们自己的应用程序中打开另一个活动。 我在这里使用TimeTask再次检查,比如5秒钟之后,如果计数器仍然是0,我们可以理所当然地认为会话已经完成。 我们还应该在每次onActivityResumed()调用时取消这个计时器(如果有的话)。

我将此行为封装在一个类上:

import java.util.Timer;
import java.util.TimerTask;

import android.util.Log;

public class UserSessionHelper {
    private static final String TAG = UserSessionHelper.class.getSimpleName();

    private static final boolean DEBUG = true;

    private static final int TIMEOUT_SECONDS = 5;

    public static interface OnUserSessionEnd {
        public void onSessionEnd(long sessionDurationinMillis);
    }

    protected OnUserSessionEnd onSessionEnd;

    protected long sessionStart = 0;
    protected int resumedActivities = 0;

    protected Timer timer = null;

    public UserSessionHelper(OnUserSessionEnd onSessionEnd) {
        this.onSessionEnd = onSessionEnd;
    }

    class EndSessionTask extends TimerTask {
        public void run() {
            if (DEBUG) {
                Log.d(TAG, "Session ended!");
            }

            timer.cancel();
            timer = null;

            long duration = System.currentTimeMillis() - sessionStart - TIMEOUT_SECONDS*1000;
            sessionStart = 0;

            onSessionEnd.onSessionEnd(duration);

        }
    }
    public void clearTimeout() {
        if (DEBUG) {
            Log.d(TAG, "Cancelling the session ending timer!");
        }

        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
    }

    public void setTimeout(int seconds) {
        timer = new Timer();
        timer.schedule(new EndSessionTask(), seconds * 1000);
    }

    public void onActivityResumed() {
        if (DEBUG) {
            Log.d(TAG, "Activity comes to foreground! " + resumedActivities);
        }       

        clearTimeout();

        if (sessionStart == 0) {
            sessionStart = System.currentTimeMillis();
        }
        resumedActivities++;

    }

    public void onActivityPaused() {
        if (DEBUG) {
            Log.d(TAG, "Activity goes to background! " + resumedActivities);
        }       

        resumedActivities--;

        if (resumedActivities == 0) {
            setTimeout(TIMEOUT_SECONDS);
        }
    }
}

并从我的自定义Applicaction类中使用它:

protected UserSessionHelper.OnUserSessionEnd mUserSessionEnded = new UserSessionHelper.OnUserSessionEnd() {

    @Override
    public void onSessionEnd(long sessionDurationinMillis) {
        if (DEBUG) {
            Log.d(TAG, "Session ended in " + (sessionDurationinMillis / 1000) + " seconds.");
        }
    }
};

public void onActivityResumed() {
    sessionHelper.onActivityResumed();
}

public void onActivityPaused() {
    sessionHelper.onActivityPaused();
}

protected UserSessionHelper sessionHelper = new UserSessionHelper(mUserSessionEnded);

在我们调用或切换到第三方应用程序一段时间并返回的情况下,这并不能解决问题(这将显示为两个会话)。关于这个的任何线索?

答案 1 :(得分:0)

使用Kotlin和Android架构组件:

//In application class
ProcessLifecycleOwner.get().getLifecycle().addObserver(appLifecycleObserver);

class AppLifecycleObserver @Inject constructor(val appConfig: ApplicationConfig) : LifecycleObserver {

  private var startTime: Long? = null

  @OnLifecycleEvent(Lifecycle.Event.ON_START)
  fun onEnterForeground() {
    startTime = System.currentTimeMillis()
  }

  @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
  private fun onEnterBackground() {
    if (startTime != null && appConfig.getBoolean(MPARTICLE_ENABLED)) {
      //Session duration
      val sessionLength = System.currentTimeMillis() - startTime!! 
    }
  }
}

答案 2 :(得分:-1)

您将获取两个整数变量,它将在会话开始时和另一个所需的时间点存储System.currentTimeMillis()的值,或者您可以定期检查时间之间的差异。