Android应用程序启动和结束事件

时间:2022-12-04 23:25:38

I have an app which track user activity on app which include time etc, Now if user has opened the app, It will start an session and till user in this app , his session will continue, He can switch to multiple activity. Now meantime he switches to another app, His session logging should be stopped and written down to file

我有一个app可以跟踪app上的用户活动,包括时间等,现在如果用户打开app,它会开始一个会话,直到用户进入这个app,他的会话会继续,他可以切换到多个活动。现在,他切换到另一个应用程序,他的会话日志记录应该被停止并记录到文件中

What I tried

我试着什么

I created one base activity and On resume event if counter is zero, I start session and increment counter and On stop event , i decrement counter and if counter is zero, I stop session

我创建了一个基本活动,如果计数器为0,我启动会话和增量计数器,在停止事件,我递减计数器,如果计数器为0,我停止会话

But this will not calculate actual problem of tracking as android doesn't stop activity as user switch to another app.

但这并不会计算追踪的实际问题,因为android不会因为用户切换到另一个应用而停止活动。

So is there any way to achieve such thing.

有什么办法可以达到这个目的呢?

Additional:

附加:

If we can get whether app activity is active on screen so event can be used to start or end session.

如果我们能在屏幕上看到app活动是否活跃,那么事件可以用来启动或结束会话。

4 个解决方案

#1


5  

I can think of two ways of doing it:

我可以想出两种方法:

Option 1:

选项1:

You can create a service which scans for the current application on the foreground and see if it is your activity. Here is some code you can use, I took it from another answer:

您可以创建一个服务,该服务扫描前台的当前应用程序并查看它是否是您的活动。这里有一些你可以使用的代码,我从另一个答案中摘录:

There's an easy way of getting a list of running tasks from the ActivityManager service. You can request a maximum number of tasks running on the phone, and by default, the currently active task is returned first.

有一种简单的方法可以从ActivityManager服务获取运行任务列表。您可以请求在电话上运行的最大数量的任务,默认情况下,先返回当前活动的任务。

Once you have that you can get a ComponentName object by requesting the topActivity from your list.

通过请求列表中的topActivity,您可以获得一个ComponentName对象。

Here's an example.

这是一个例子。

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);

     // get the info from the currently running task
     List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1); 

     Log.d("topActivity", "CURRENT Activity ::"
             + taskInfo.get(0).topActivity.getClassName());

     ComponentName componentInfo = taskInfo.get(0).topActivity;
   componentInfo.getPackageName();

You will need the following permission on your manifest:

你在舱单上需要以下许可:

<uses-permission android:name="android.permission.GET_TASKS"/>

Link to the answer: Android: How can I get the current foreground activity (from a service)?

链接到答案:Android:如何获得当前前台活动(从服务)?

You can call this every one second or less to detect if your app is still active. Please note that it is a deprecated and is not recommended for using for this kind of things, according to official documentation:

你可以每一秒钟或更少地调用一次,以检测你的应用程序是否仍然处于活动状态。请注意,这是一个弃用,不建议用于此类事情,根据官方文件:

getRunningTasks()

getRunningTasks()

Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect.

注意:此方法仅用于调试和显示任务管理用户界面。在应用程序中,不应该将其用于核心逻辑,例如根据这里找到的信息来决定不同的行为。这种用途不受支持,将来可能会中断。例如,如果多个应用程序可以同时运行,那么为了控制流而对这里数据的含义所作的假设将是不正确的。


Option 2:

选项2:

The second option is to create a class that extends Application with a flag, for example isAppRunning, which will be true or false according if your application is on the foreground or not:

第二个选项是创建一个类来扩展应用程序,例如isAppRunning,如果您的应用程序在前台或不在前台,它将是真或假:

public class MyAppContext extends Application {

   public boolean isAppRunning = true;

   public void setIsAppRunning(boolean v){
      isAppRunning = v;
   }

   public boolean isAppRunning(){
      return isAppRunning;
   }

}

Then on your AndroidManifest.xml you have to add this class so it will be used when your application starts. Just add android:name=".MyAppContext" under the application tag:

然后在你的AndroidManifest。您必须添加这个类,以便在应用程序启动时使用它。把android:name = "。MyAppContext“在应用程序标签下:

<application
        android:name=".MyAppContext"

Now in every activity that you have you should override onResume() and onPause() and set the flag to the corresponding value:

现在,在您拥有的每个活动中,都应该重写onResume()和onPause(),并将标记设置为相应的值:

class BaseActivity extends Activity {


    @Override
    protected void onResume() {
        super.onResume();
        ((MyAppContext)getApplication()).setIsAppRunning(true);
    }

    @Override
    protected void onPause() {
        ((MyAppContext)getApplication()).setIsAppRunning(false);
        super.onPause();
    }
}

On this way every time you start an Activity the value of isAppRunning in MyAppContext will be true, when you exit the Activity it will be false but if another Activity opens (for example if you pressed the back button so you are returning to the previous activity) the value will be immediately true again.

这样每次你启动一个活动MyAppContext isAppRunning将真正的价值,当你退出活动将是错误的,但如果打开另一个活动(例如,如果您按下后退按钮返回到以前的活动)的值将被立即又真实。

When you finally finish all your Activities none of the onResume() methods will be called and all the onPause() methods will be called so isAppRunning will be false and you know your Activity is no longer on the foreground.

当您最终完成所有的活动时,将调用onResume()方法,而所有onPause()方法将被调用,因此isAppRunning将是错误的,您知道您的活动已经不在前台了。

So resuming, if isAppRunning is true your application is on the foreground (start the session tracking) otherwise it's gone (stop the session tracking). You can create a Timer in MyAppContext class to check the value of isAppRunning periodically, so it would be:

因此,如果isAppRunning是true,那么应用程序就位于前台(启动会话跟踪),否则它就会消失(停止会话跟踪)。您可以在MyAppContext类中创建一个计时器来定期检查isAppRunning的值,所以它是:

public class MyAppContext extends Application {

   public boolean isAppRunning = true;
   public final int timerRate = 500;    // Execute timer task every 500mS

   public void setIsAppRunning(boolean v){
      isAppRunning = v;
   }

   public boolean isAppRunning(){
      return isAppRunning;
   }

   @Override
   public void onCreate() {
      super.onCreate();
      Timer mTimer = new Timer();

      mTimer.scheduleAtFixedRate(new TimerTask() {
         @Override
         public void run() {
            if(isAppRunning) startSesionTracking();
            else stopSesionTracking();
         }
      }, 0, REFRESH_TIME);
   }

   private void startSesionTracking () { ... };
   private void stopSesionTracking () { ... };

}

You should modify timerRate according to the precision you want to get in your session tracking.

您应该根据希望在会话跟踪中获得的精度修改timerRate。

#2


2  

Extend all your Activities from BaseActivity like below. This is the best option for you as onPause and onResume methods are guaranteed to be called whenever your Activities show up or go away from phone screen.

从BaseActivity扩展所有活动,如下所示。这是你最好的选择,当你的活动出现或离开手机屏幕的时候,你就可以选择onPause和onResume方法。

class BaseActivity extends Activity {


    @Override
    protected void onResume() {
        super.onResume();
        // Start Logging
    }

    @Override
    protected void onPause() {
        super.onPause();
        // End Logging
    }
}

#3


0  

You need to look into Activity lifecycles on Android.

您需要查看Android上的活动生命周期。

What you need is onPause - see the documentation here

您需要的是onPause—请参阅这里的文档

I would also mention that onPause is fired even when switching between multiple activities, so you'd need to track when it's pausing to go to another screen.

我还要提到,即使在切换多个活动时,onPause也会被触发,因此您需要跟踪它何时暂停,以便转到另一个屏幕。

#4


0  

1.Create a class named AppLifecycleTracker and paste this.

1。创建一个名为AppLifecycleTracker的类并粘贴它。

private class AppLifecycleTracker implements ActivityLifecycleCallbacks {
            private int numStarted = 0;
            private String TAG = "AppLifecycleTracker";


            private int numOfCreated = 0;

            @Override`enter code here`
            public void onActivityCreated(Activity activity, Bundle bundle) {
                if (numOfCreated == 0) {
                    Log.d(TAG, "onActivityCreated: app started");
                }
                numOfCreated++;
                Log.d(TAG, "onActivityCreated: " + numOfCreated);
            }

            @Override
            public void onActivityStarted(Activity activity) {
                if (numStarted == 0) {
                    // app went to foreground
                    Log.d(TAG, "onActivityStarted: foreground");

                }
                numStarted++;


            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                numStarted--;
                if (numStarted == 0) {
                    // app went to background
                    Log.d(TAG, "onActivityStarted: background");

                }
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                numOfCreated--;
                Log.d(TAG, "onActivityDestroyed: " + numOfCreated);
            }
        }

* in onActivityCreate if numOfCreated = 0, then you can say app has started. * in onActivityDestroyed if numOfCreated = 0, then you can say app is closed.

*在onActivityCreate中,如果numofcreate = 0,则可以说app已经启动。*在onActivityDestroyed中,如果numOfCreated = 0,则可以说app已经关闭。

  1. Create a class extending Application, in onCreate, add this line

    在onCreate中创建一个类扩展应用程序,添加这一行

    registerActivityLifecycleCallbacks(new AppLifecycleTracker());

    registerActivityLifecycleCallbacks(新AppLifecycleTracker());

  2. set application name as the Application class in manifest.xml

    将应用程序名称设置为manifest.xml中的应用程序类

Thats it. You are good to go.

这是它。你真好。

#1


5  

I can think of two ways of doing it:

我可以想出两种方法:

Option 1:

选项1:

You can create a service which scans for the current application on the foreground and see if it is your activity. Here is some code you can use, I took it from another answer:

您可以创建一个服务,该服务扫描前台的当前应用程序并查看它是否是您的活动。这里有一些你可以使用的代码,我从另一个答案中摘录:

There's an easy way of getting a list of running tasks from the ActivityManager service. You can request a maximum number of tasks running on the phone, and by default, the currently active task is returned first.

有一种简单的方法可以从ActivityManager服务获取运行任务列表。您可以请求在电话上运行的最大数量的任务,默认情况下,先返回当前活动的任务。

Once you have that you can get a ComponentName object by requesting the topActivity from your list.

通过请求列表中的topActivity,您可以获得一个ComponentName对象。

Here's an example.

这是一个例子。

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);

     // get the info from the currently running task
     List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1); 

     Log.d("topActivity", "CURRENT Activity ::"
             + taskInfo.get(0).topActivity.getClassName());

     ComponentName componentInfo = taskInfo.get(0).topActivity;
   componentInfo.getPackageName();

You will need the following permission on your manifest:

你在舱单上需要以下许可:

<uses-permission android:name="android.permission.GET_TASKS"/>

Link to the answer: Android: How can I get the current foreground activity (from a service)?

链接到答案:Android:如何获得当前前台活动(从服务)?

You can call this every one second or less to detect if your app is still active. Please note that it is a deprecated and is not recommended for using for this kind of things, according to official documentation:

你可以每一秒钟或更少地调用一次,以检测你的应用程序是否仍然处于活动状态。请注意,这是一个弃用,不建议用于此类事情,根据官方文件:

getRunningTasks()

getRunningTasks()

Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect.

注意:此方法仅用于调试和显示任务管理用户界面。在应用程序中,不应该将其用于核心逻辑,例如根据这里找到的信息来决定不同的行为。这种用途不受支持,将来可能会中断。例如,如果多个应用程序可以同时运行,那么为了控制流而对这里数据的含义所作的假设将是不正确的。


Option 2:

选项2:

The second option is to create a class that extends Application with a flag, for example isAppRunning, which will be true or false according if your application is on the foreground or not:

第二个选项是创建一个类来扩展应用程序,例如isAppRunning,如果您的应用程序在前台或不在前台,它将是真或假:

public class MyAppContext extends Application {

   public boolean isAppRunning = true;

   public void setIsAppRunning(boolean v){
      isAppRunning = v;
   }

   public boolean isAppRunning(){
      return isAppRunning;
   }

}

Then on your AndroidManifest.xml you have to add this class so it will be used when your application starts. Just add android:name=".MyAppContext" under the application tag:

然后在你的AndroidManifest。您必须添加这个类,以便在应用程序启动时使用它。把android:name = "。MyAppContext“在应用程序标签下:

<application
        android:name=".MyAppContext"

Now in every activity that you have you should override onResume() and onPause() and set the flag to the corresponding value:

现在,在您拥有的每个活动中,都应该重写onResume()和onPause(),并将标记设置为相应的值:

class BaseActivity extends Activity {


    @Override
    protected void onResume() {
        super.onResume();
        ((MyAppContext)getApplication()).setIsAppRunning(true);
    }

    @Override
    protected void onPause() {
        ((MyAppContext)getApplication()).setIsAppRunning(false);
        super.onPause();
    }
}

On this way every time you start an Activity the value of isAppRunning in MyAppContext will be true, when you exit the Activity it will be false but if another Activity opens (for example if you pressed the back button so you are returning to the previous activity) the value will be immediately true again.

这样每次你启动一个活动MyAppContext isAppRunning将真正的价值,当你退出活动将是错误的,但如果打开另一个活动(例如,如果您按下后退按钮返回到以前的活动)的值将被立即又真实。

When you finally finish all your Activities none of the onResume() methods will be called and all the onPause() methods will be called so isAppRunning will be false and you know your Activity is no longer on the foreground.

当您最终完成所有的活动时,将调用onResume()方法,而所有onPause()方法将被调用,因此isAppRunning将是错误的,您知道您的活动已经不在前台了。

So resuming, if isAppRunning is true your application is on the foreground (start the session tracking) otherwise it's gone (stop the session tracking). You can create a Timer in MyAppContext class to check the value of isAppRunning periodically, so it would be:

因此,如果isAppRunning是true,那么应用程序就位于前台(启动会话跟踪),否则它就会消失(停止会话跟踪)。您可以在MyAppContext类中创建一个计时器来定期检查isAppRunning的值,所以它是:

public class MyAppContext extends Application {

   public boolean isAppRunning = true;
   public final int timerRate = 500;    // Execute timer task every 500mS

   public void setIsAppRunning(boolean v){
      isAppRunning = v;
   }

   public boolean isAppRunning(){
      return isAppRunning;
   }

   @Override
   public void onCreate() {
      super.onCreate();
      Timer mTimer = new Timer();

      mTimer.scheduleAtFixedRate(new TimerTask() {
         @Override
         public void run() {
            if(isAppRunning) startSesionTracking();
            else stopSesionTracking();
         }
      }, 0, REFRESH_TIME);
   }

   private void startSesionTracking () { ... };
   private void stopSesionTracking () { ... };

}

You should modify timerRate according to the precision you want to get in your session tracking.

您应该根据希望在会话跟踪中获得的精度修改timerRate。

#2


2  

Extend all your Activities from BaseActivity like below. This is the best option for you as onPause and onResume methods are guaranteed to be called whenever your Activities show up or go away from phone screen.

从BaseActivity扩展所有活动,如下所示。这是你最好的选择,当你的活动出现或离开手机屏幕的时候,你就可以选择onPause和onResume方法。

class BaseActivity extends Activity {


    @Override
    protected void onResume() {
        super.onResume();
        // Start Logging
    }

    @Override
    protected void onPause() {
        super.onPause();
        // End Logging
    }
}

#3


0  

You need to look into Activity lifecycles on Android.

您需要查看Android上的活动生命周期。

What you need is onPause - see the documentation here

您需要的是onPause—请参阅这里的文档

I would also mention that onPause is fired even when switching between multiple activities, so you'd need to track when it's pausing to go to another screen.

我还要提到,即使在切换多个活动时,onPause也会被触发,因此您需要跟踪它何时暂停,以便转到另一个屏幕。

#4


0  

1.Create a class named AppLifecycleTracker and paste this.

1。创建一个名为AppLifecycleTracker的类并粘贴它。

private class AppLifecycleTracker implements ActivityLifecycleCallbacks {
            private int numStarted = 0;
            private String TAG = "AppLifecycleTracker";


            private int numOfCreated = 0;

            @Override`enter code here`
            public void onActivityCreated(Activity activity, Bundle bundle) {
                if (numOfCreated == 0) {
                    Log.d(TAG, "onActivityCreated: app started");
                }
                numOfCreated++;
                Log.d(TAG, "onActivityCreated: " + numOfCreated);
            }

            @Override
            public void onActivityStarted(Activity activity) {
                if (numStarted == 0) {
                    // app went to foreground
                    Log.d(TAG, "onActivityStarted: foreground");

                }
                numStarted++;


            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                numStarted--;
                if (numStarted == 0) {
                    // app went to background
                    Log.d(TAG, "onActivityStarted: background");

                }
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                numOfCreated--;
                Log.d(TAG, "onActivityDestroyed: " + numOfCreated);
            }
        }

* in onActivityCreate if numOfCreated = 0, then you can say app has started. * in onActivityDestroyed if numOfCreated = 0, then you can say app is closed.

*在onActivityCreate中,如果numofcreate = 0,则可以说app已经启动。*在onActivityDestroyed中,如果numOfCreated = 0,则可以说app已经关闭。

  1. Create a class extending Application, in onCreate, add this line

    在onCreate中创建一个类扩展应用程序,添加这一行

    registerActivityLifecycleCallbacks(new AppLifecycleTracker());

    registerActivityLifecycleCallbacks(新AppLifecycleTracker());

  2. set application name as the Application class in manifest.xml

    将应用程序名称设置为manifest.xml中的应用程序类

Thats it. You are good to go.

这是它。你真好。