计算会话长度android
如何计算Android中用户的会话长度,以便我可以在合适的时间推送广告? 有没有可以帮助我的图书馆。 我正在使用谷歌分析来获得平均会话长度,但我如何获得个人用户?
我发现了同样的问题,并就这个问题做了一些研究。 我的结论是:
定义用户会话是一件相当复杂的事情。
-
“你打开(第三方)电子邮件应用程序来写你的应用程序和会议的反馈部分吗?” 这同样适用于任何共享应用程序或任何播放器。
-
当用户切换回另一个应用程序来检查其他应用程序上的任何内容并返回时,是您的应用程序会话的一部分。 注意我不是在说前面的情况,我的意思是用户使用menu / desktop / applist按钮来切换。
-
当设备由于不活动而暂时进入睡眠模式时,会话计时器是否应继续计数? 当用户唤醒他的设备时,你的应用程序将仍然在前台。
我也发现了一些Android特定的问题:
-
Android没有应用程序会话长度的本地概念。 也就是说,用户在前台花了多少时间在应用上。
-
一个Android应用程序实际上是一系列的屏幕(活动)。
-
Android有一个应用程序类,但它不是如何以及何时被创建/杀死的。 这是一个操作系统的任务。 你的应用程序可能在后台,但你的应用程序类可能仍然在内存中。
-
一些方法是不可靠的,依靠他们被调用,像Activity.OnStop(见http://developer.android.com/intl/es/reference/android/app/Activity.html#onStop() )
所以我最终的解决方案是:
在Application上添加一个定时器(其实就是一个简单的长时间关注一个System.currentTimeMillis()添加一个“打开”活动计数器,在Application.onCreate()上初始化为0,
将一个onActivityResumed()方法添加到应用程序。 如果以前的计数器值为0,我应该递增计数器并初始化计时器。添加到所有活动onResume()调用Application.onActivityResumed()
将一个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);
这并不能解决我们打电话或切换到第三方应用程序一段时间并返回的情况(这将显示为两个会话)。 任何线索在这一个?
使用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!! } } }
您需要两个整数variables,它们将在会话开始时和另一个期望的时间点存储System.currentTimeMillis()的值,或者您可以定期检查时间之间的差异。
- 无法获取提供者android.arch.lifecycle.LifecycleRuntimeTrojanProvider:java.lang.ClassNotFoundException
- 如何在Android项目中的Java模块上模拟Mockito 2的最终课程?
- 如何通过setOnEditorActionListener关闭android alert对话框本身?
- 当我退出应用程序时,为什么在Android应用程序中使用Kotlin / rxJava编写android.os.TransactionTooLargeException? (的OnExit /的onPause)?
- 握手使用okHttp失败,但使用HttpURLConnection工作
- 为android @Multipart改装删除默认标题
- 使用Kotlin自定义Android视图
- Kotlin数据库错误CursorIndexOutOfBoundsException
- 如何在处理程序中将java转换为kotlin