如何在Android中检测用户不活动


101

用户启动我的应用并登录。
选择“会话超时”为5分钟。
在应用程序上执行一些操作。(全部在前景中)
现在,用户将Myapp置于后台并启动其他一些应用程序。
---->倒数计时器启动并在5分钟后注销用户,
或者用户将屏幕关闭。
---->倒数计时器启动并在5分钟后注销用户

即使应用程序位于前台,但用户长时间不说与应用程序交互(例如6-7分钟),我也希望得到相同的行为。假设屏幕一直处于打开状态。我想检测某种用户不活动状态(即使应用程序在前台也不会与应用程序进行交互),然后启动我的倒数计时器。


1
您可以一直运行该计时器,并在用户执行任何操作时将其重置吗?
凯尔·P

Answers:


111

根据Fredrik Wallenius的回答,我想出了一个非常简单的解决方案。这是一个基本活动类,所有活动都需要扩展它。

public class MyBaseActivity extends Activity {

    public static final long DISCONNECT_TIMEOUT = 300000; // 5 min = 5 * 60 * 1000 ms


    private static Handler disconnectHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            // todo
            return true;
        }
    });

    private static Runnable disconnectCallback = new Runnable() {
        @Override
        public void run() {
            // Perform any required operation on disconnect
        }
    };

    public void resetDisconnectTimer(){
        disconnectHandler.removeCallbacks(disconnectCallback);
        disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
    }

    public void stopDisconnectTimer(){
        disconnectHandler.removeCallbacks(disconnectCallback);
    }

    @Override
    public void onUserInteraction(){
        resetDisconnectTimer();
    }

    @Override
    public void onResume() {
        super.onResume();
        resetDisconnectTimer();
    }

    @Override
    public void onStop() {
        super.onStop();
        stopDisconnectTimer();
    }
}

3
这将创建的多个实例Handler,并Runnable为每个Activity创建的。如果我们将这两个成员转换为static,将避免这种情况。另外,你能告诉我,为什么你叫stopDisconnectTimer()onStop()'?
拉夫Bhor

@Gaurav在我的情况下,这仅在一个活动中实现(因此我没有发现使用static修饰符的问题)。至于onStop()我记得的,我onBackPressed()为了在断开回调中返回登录屏幕而调用,该回调又调用该onStop()方法。当用户手动返回登录屏幕时,通过按回去,计时器也需要停止,因此stopDisconnectTimer()in onStop()。我想这部分取决于您的需求和实现。
gfrigon 2014年

@gfrigon是否可以将用户重定向到登录活动?
Apostrofix

@Apostrifix,当然可以。就我而言,只有一种活动:调用onBackPressed()vas足够。如果堆栈中有多个活动,则只需为此创建一个意图。你可能想看看下面的答案,以明确活动任务(以及防止用户重新连接上一回):stackoverflow.com/questions/7075349/...
gfrigon

做得好!我为可运行对象添加了getter和setter,然后根据需要使用onCreate方法将其设置在扩展类中……非常完美,再次感谢您。
CrandellWS

90

我不知道一种跟踪不活动的方法,但是有一种跟踪用户活动的方法。您可以捕获onUserInteraction()活动中调用的回调,该回调在用户每次与应用程序进行任何交互时都会调用。我建议做这样的事情:

@Override
public void onUserInteraction(){
    MyTimerClass.getInstance().resetTimer();
}

如果您的应用程序包含多个活动,为什么不将该方法放在抽象的超类中(扩展Activity),然后让您进行的所有活动都对其进行扩展。


1
是的,这是一种实现方式...但是我的应用程序有30种不同的活动,并且当用户处于活动状态时互动会过多...因此每次重置计时器都将是一项昂贵的操作...最坏的情况是在一分钟内可能发生50到60次。
2010年

3
我还没有计时,但我想说说要重置一个计时器,例如lastInteraction = System.currentTimeMillis();。大概需要2毫秒。每分钟执行60次,您就会“松散” 120毫秒。出于60000
弗雷德里克华轮

1
Fredrik ...我也正在使用您的建议来满足这种情况。屏幕超时设置为设备上的最长30分钟。15分钟后MyApp shd超时...如果用户超过1分钟未触摸屏幕上的任何内容,则我将启动15min注销计时器...。在这种情况下,我将检查是否存在差异(lastInteractionTime和System.currentTimeMills( ))超过1分钟...然后开火..
10年

3
但是在某些情况下不会调用onUserInteraction()(对话不调用它,并且在微调器中滚动)是否可以解决这些情况?
AndroidNoob 2014年

您可以分享您的MyTimerClass吗?
西贝柳斯·塞拉菲尼

19

我认为您应该使用此代码,这是5分钟的空闲会话超时:->

Handler handler;
Runnable r;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    handler = new Handler();
    r = new Runnable() {

       @Override
       public void run() {
            // TODO Auto-generated method stub
            Toast.makeText(MainActivity.this, "user is inactive from last 5 minutes",Toast.LENGTH_SHORT).show();
        }
    };
    startHandler();
}
@Override
public void onUserInteraction() {
     // TODO Auto-generated method stub
     super.onUserInteraction();
     stopHandler();//stop first and then start
     startHandler();
}
public void stopHandler() {
    handler.removeCallbacks(r);
}
public void startHandler() {
    handler.postDelayed(r, 5*60*1000); //for 5 minutes 
}

您通过onUserInteraction拯救了我的性命
codezombie

10
public class MyApplication extends Application {
      private int lastInteractionTime;
      private Boolean isScreenOff = false; 
      public void onCreate() {
        super.onCreate();
        // ......   
        startUserInactivityDetectThread(); // start the thread to detect inactivity
        new ScreenReceiver();  // creating receive SCREEN_OFF and SCREEN_ON broadcast msgs from the device.
      }

      public void startUserInactivityDetectThread() {
        new Thread(new Runnable() {
          @Override
          public void run() {
            while(true) {
              Thread.sleep(15000); // checks every 15sec for inactivity
              if(isScreenOff || getLastInteractionTime()> 120000 ||  !isInForeGrnd)
                {
                  //...... means USER has been INACTIVE over a period of
                  // and you do your stuff like log the user out 
                }
              }
          }
        }).start();
      }

      public long getLastInteractionTime() {
        return lastInteractionTime;
      }

      public void setLastInteractionTime(int lastInteractionTime) {
        this.lastInteractionTime = lastInteractionTime;
      }

      private class ScreenReceiver extends BroadcastReceiver {

        protected ScreenReceiver() {
           // register receiver that handles screen on and screen off logic
           IntentFilter filter = new IntentFilter();
           filter.addAction(Intent.ACTION_SCREEN_ON);
           filter.addAction(Intent.ACTION_SCREEN_OFF);
           registerReceiver(this, filter);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
          if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            isScreenOff = true;
          } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            isScreenOff = false;
          }
        }
      }
    }

isInForeGrnd ===>此处未显示逻辑,因为它超出了问题的范围

您可以使用以下设备代码唤醒对CPU的锁定-

  if(isScreenOff || getLastInteractionTime()> 120000 ||  !isInForeGrnd)
    {
      //...... means USER has been INACTIVE over a period of
      // and you do your stuff like log the user out 

      PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

      boolean isScreenOn = pm.isScreenOn();
      Log.e("screen on.................................", "" + isScreenOn);

      if (isScreenOn == false) {

        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "MyLock");

        wl.acquire(10000);
        PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyCpuLock");

        wl_cpu.acquire(10000);
      }
    }

4
@Nappy:然后请说明正确的方法。您的评论含糊而优柔寡断。
2011年

2
@AKh:其他答案已经显示出了可能性。在您的解决方案中,每15秒进行一次轮询不会带来任何好处。效果与您在“ ACTION_SCREEN_OFF”上启动计时器(具有0到15秒的随机持续时间)相同。这只是没有道理
。-尿布

1
@Nappy:每隔15秒,我不仅检查SCREEN_ON或SCREEN_OFF,还检查用户的上次交互时间和应用程序前台状态。基于这三个因素,我对用户与应用程序交互的活跃程度做出了合理的决定。
2011年

请完成您的评论。....“如果您的isScreenof布尔值是?” 并且还必须考虑应用程序的前备状态。
2011年

1
该代码充满错误,某些变量未初始化。
Big.Child 2013年

8
@Override
public void onUserInteraction() {
    super.onUserInteraction();
    delayedIdle(IDLE_DELAY_MINUTES);
}

Handler _idleHandler = new Handler();
Runnable _idleRunnable = new Runnable() {
    @Override
    public void run() {
        //handle your IDLE state
    }
};

private void delayedIdle(int delayMinutes) {
    _idleHandler.removeCallbacks(_idleRunnable);
    _idleHandler.postDelayed(_idleRunnable, (delayMinutes * 1000 * 60));
}

这是解决方案的基础,其余的可以根据您的特殊需求和应用程序体系结构的复杂性进行修改!感谢你的回答!
Hack06

如何在应用程序类中应用此方法
Gaju Kollur,

6

除了ACTION_SCREEN_OFFACTION_USER_PRESENT广播之外,在OS级别上没有“用户不活动”的概念。您将必须在自己的应用程序中以某种方式定义“不活动”。


6

即使您可以使用@gfrigon@AKh来管理您的需求解决方案。

但是,这是计时器和处理程序的免费解决方案。我已经有很好的定时器解决方案。但是我已经成功实现了Timer和Handler的免费解决方案。

首先,我告诉您使用计时器或处理程序时必须管理的内容

  • 如果您的应用被用户或优化器杀死,则您的应用将永远不会自动注销,因为所有回调都已销毁。(管理一些警报管理器或服务?
  • 每个基类都有计时器好吗?您正在为调用注销过程创建许多线程(在应用程序级别管理静态处理程序或计时器?)。
  • 如果用户在后台该怎么办,如果用户在应用程序之外执行其他工作,则处理程序将启动“登录活动”。(管理应用程序的前台还是后台?)。
  • 屏幕自动关闭怎么办。(是否在广播接收器上关闭屏幕?

最后,我实现了一个解决方案

  1. 没有处理程序或计时器。
  2. 否警报管理器。
  3. 不管理App LifeCycle。
  4. ACTION_SCREEN_ON/ ACTION_SCREEN_OFF广播接收器。

最简单可靠的解决方案

我们不会通过计时器观察到用户处于不活动状态,而是会检查用户活动的上次活动时间。因此,当用户下次与应用交互时,我会检查上一次的交互时间。

这里是BaseActivity.class你会从每一个你的活动类,而不是延长LoginActivity。您将TIMEOUT_IN_MILLI在此类的字段中定义注销时间。

import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

public class BaseActivity extends AppCompatActivity {
    public static final long TIMEOUT_IN_MILLI = 1000 * 20;
    public static final String PREF_FILE = "App_Pref";
    public static final String KEY_SP_LAST_INTERACTION_TIME = "KEY_SP_LAST_INTERACTION_TIME";

    @Override
    public void onUserInteraction() {
        super.onUserInteraction();
        if (isValidLogin())
            getSharedPreference().edit().putLong(KEY_SP_LAST_INTERACTION_TIME, System.currentTimeMillis()).apply();
        else logout();
    }

    public SharedPreferences getSharedPreference() {
        return getSharedPreferences(PREF_FILE, MODE_PRIVATE);
    }

    public boolean isValidLogin() {
        long last_edit_time = getSharedPreference().getLong(KEY_SP_LAST_INTERACTION_TIME, 0);
        return last_edit_time == 0 || System.currentTimeMillis() - last_edit_time < TIMEOUT_IN_MILLI;
    }

    public void logout() {
        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
        finish();
        Toast.makeText(this, "User logout due to inactivity", Toast.LENGTH_SHORT).show();
        getSharedPreference().edit().remove(KEY_SP_LAST_INTERACTION_TIME).apply(); // make shared preference null.
    }
}

与每次调用多个线程相比,如何在每次用户交互时访问主线程上的共享首选项都更好。
西田

@Nishita发布此答案时,我还没有意识到这一缺点。感谢您对我的1个错误答案发表评论。没错,这不是正确的方法。我将隐藏此答案。
Khemraj

2

在活动基类中,我创建了受保护的类:

protected class IdleTimer
{
    private Boolean isTimerRunning;
    private IIdleCallback idleCallback;
    private int maxIdleTime;
    private Timer timer;

    public IdleTimer(int maxInactivityTime, IIdleCallback callback)
    {
        maxIdleTime = maxInactivityTime;
        idleCallback = callback;
    }

    /*
     * creates new timer with idleTimer params and schedules a task
     */
    public void startIdleTimer()
    {
        timer = new Timer();            
        timer.schedule(new TimerTask() {

            @Override
            public void run() {             
                idleCallback.inactivityDetected();
            }
        }, maxIdleTime);
        isTimerRunning = true;
    }

    /*
     * schedules new idle timer, call this to reset timer
     */
    public void restartIdleTimer()
    {
        stopIdleTimer();
        startIdleTimer();
    }

    /*
     * stops idle timer, canceling all scheduled tasks in it
     */
    public void stopIdleTimer()
    {
        timer.cancel();
        isTimerRunning = false;
    }

    /*
     * check current state of timer
     * @return boolean isTimerRunning
     */
    public boolean checkIsTimerRunning()
    {
        return isTimerRunning;
    }
}

protected interface IIdleCallback
{
    public void inactivityDetected();
}

因此,在onResume方法中-您可以在回调中指定操作,您希望如何处理...

idleTimer = new IdleTimer(60000, new IIdleCallback() {
            @Override
            public void inactivityDetected() {
                ...your move...
            }
        });
        idleTimer.startIdleTimer();

如何检查用户不活跃?来自系统的任何输入?
MohsinSyd 2014年

2

在搜索过程中,我找到了很多答案,但这是我得到的最佳答案。但是此代码的局限性在于它仅适用于活动,不适用于整个应用程序。以此为参考。

myHandler = new Handler();
myRunnable = new Runnable() {
    @Override
    public void run() {
        //task to do if user is inactive

    }
};
@Override
public void onUserInteraction() {
    super.onUserInteraction();
    myHandler.removeCallbacks(myRunnable);
    myHandler.postDelayed(myRunnable, /*time in milliseconds for user inactivity*/);
}

例如,您使用8000,则该任务将在用户不活动8秒后完成。


2

用户不活动可以使用onUserInteraction()android中的替代方法进行检测

  @Override
    public void onUserInteraction() {
        super.onUserInteraction();

    }

这是示例代码, 用户不活动3分钟后注销(HomeActivity-> LoginActivity)

public class HomeActivity extends AppCompatActivity {

    private static String TAG = "HomeActivity";
    private Handler handler;
    private Runnable r;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);


        handler = new Handler();
        r = new Runnable() {

            @Override
            public void run() {

                Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
                startActivity(intent);
                Log.d(TAG, "Logged out after 3 minutes on inactivity.");
                finish();

                Toast.makeText(HomeActivity.this, "Logged out after 3 minutes on inactivity.", Toast.LENGTH_SHORT).show();
            }
        };

        startHandler();

    }

    public void stopHandler() {
        handler.removeCallbacks(r);
        Log.d("HandlerRun", "stopHandlerMain");
    }

    public void startHandler() {
        handler.postDelayed(r, 3 * 60 * 1000);
        Log.d("HandlerRun", "startHandlerMain");
    }

    @Override
    public void onUserInteraction() {
        super.onUserInteraction();
        stopHandler();
        startHandler();
    }

    @Override
    protected void onPause() {

        stopHandler();
        Log.d("onPause", "onPauseActivity change");
        super.onPause();

    }

    @Override
    protected void onResume() {
        super.onResume();
        startHandler();

        Log.d("onResume", "onResume_restartActivity");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopHandler();
        Log.d("onDestroy", "onDestroyActivity change");

    }

}

2

在KOTLIN中处理用户交互超时:

     //Declare handler
      private var timeoutHandler: Handler? = null
      private var interactionTimeoutRunnable: Runnable? = null

 override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_aspect_ratio)

       //Initialise handler
      timeoutHandler =  Handler();
      interactionTimeoutRunnable =  Runnable {
         // Handle Timeout stuffs here
          }

      //start countdown
      startHandler()
}

// reset handler on user interaction
override fun onUserInteraction() {
      super.onUserInteraction()
      resetHandler()
}

 //restart countdown
fun resetHandler() {
      timeoutHandler?.removeCallbacks(interactionTimeoutRunnable);
      timeoutHandler?.postDelayed(interactionTimeoutRunnable, 10*1000); //for 10 second

}

 // start countdown
fun startHandler() {
    timeoutHandler?.postDelayed(interactionTimeoutRunnable, 10*1000); //for 10 second
}

1

这是一个完整的解决方案,可以处理几分钟(例如3分钟)后的用户不活动状态。这解决了一些常见问题,例如,当应用程序在后台超时时,“活动”跳入前台。

首先,我们创建一个BaseActivity,所有其他Activity都可以扩展。

这是BaseActivity代码。

package com.example.timeout;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;


import javax.annotation.Nullable;

public class BaseActivity extends AppCompatActivity implements LogoutListener {

    private Boolean isUserTimedOut = false;
    private static Dialog mDialog;



    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((TimeOutApp) getApplication()).registerSessionListener(this);
        ((TimeOutApp) getApplication()).startUserSession();

    }

    @Override
    public void onUserInteraction() {
        super.onUserInteraction();


    }

    @Override
    protected void onResume() {
        super.onResume();

        if (isUserTimedOut) {
            //show TimerOut dialog
            showTimedOutWindow("Time Out!", this);

        } else {

            ((TimeOutApp) getApplication()).onUserInteracted();

        }

    }

    @Override
    public void onSessionLogout() {


        isUserTimedOut = true;

    }


    public void showTimedOutWindow(String message, Context context) {


        if (mDialog != null) {
            mDialog.dismiss();
        }
        mDialog = new Dialog(context);


        mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        mDialog.setContentView(R.layout.dialog_window);

        mDialog.setCancelable(false);
        mDialog.setCanceledOnTouchOutside(false);

        TextView mOkButton = (TextView) mDialog.findViewById(R.id.text_ok);
        TextView text_msg = (TextView) mDialog.findViewById(R.id.text_msg);

        if (message != null && (!TextUtils.isEmpty(message)) && (!message.equalsIgnoreCase("null"))) {
            text_msg.setText(message);

        }


        mOkButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (mDialog != null){

                    mDialog.dismiss();

                    Intent intent = new Intent(BaseActivity.this, LoginActivity.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(intent);

                    finish();
                }


            }
        });

        if(!((Activity) context).isFinishing())
        {
            //show dialog
            mDialog.show();
        }

    }

}

接下来,我们为“注销监听器”创建一个接口

package com.example.timeout;

public interface LogoutListener {

    void onSessionLogout();

}

最后,我们创建一个扩展“应用程序”的Java类。

package com.example.timeout;

import android.app.Application;

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

public class TimeOutApp extends Application {

    private LogoutListener listener;
    private Timer timer;
    private static final long INACTIVE_TIMEOUT = 180000; // 3 min


    public void startUserSession () {
        cancelTimer ();

        timer = new Timer ();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {

                listener.onSessionLogout ();

            }
        }, INACTIVE_TIMEOUT);

    }

    private void cancelTimer () {
        if (timer !=null) timer.cancel();
    }

    public void registerSessionListener(LogoutListener listener){
        this.listener = listener;
    }

    public void onUserInteracted () {
        startUserSession();
    }


}

注意:不要忘记在清单文件中的应用程序标签中添加“ TimeOutApp”类

<application
        android:name=".TimeOutApp">
        </application>

0

我认为必须将计时器与上次激活时间结合起来。

像这样:

  1. 在onCreate(Bundle savedInstanceState)中启动一个计时器,说5分钟

  2. 在onUserInteraction()中只存储当前时间

到目前为止非常简单。

现在,当计时器弹出时,请执行以下操作:

  1. 取当前时间并减去存储的交互时间即可得出timeDelta
  2. 如果timeDelta> = 5分钟,就完成了
  3. 如果timeDelta <5分钟,请重新启动计时器,但是这次使用5分钟-存储的时间。换句话说,最后一次互动是5分钟

0

我有类似的问题,所以我需要跟踪用户1分钟的不活动状态,然后重定向用户以启动“活动”,我还需要清除活动堆栈。

基于@gfrigon答案,我想出了这个解决方案。

ActionBar.java

public abstract class ActionBar extends AppCompatActivity {

    public static final long DISCONNECT_TIMEOUT = 60000; // 1 min

    private final MyHandler mDisconnectHandler = new MyHandler(this);

    private Context mContext;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mContext = this;
    }



    /*
    |--------------------------------------------------------------------------
    | Detect user inactivity in Android
    |--------------------------------------------------------------------------
    */

    // Static inner class doesn't hold an implicit reference to the outer class

    private static class MyHandler extends Handler {

        // Using a weak reference means you won't prevent garbage collection

        private final WeakReference<ActionBar> myClassWeakReference;

        public MyHandler(ActionBar actionBarInstance) {

            myClassWeakReference = new WeakReference<ActionBar>(actionBarInstance);
        }

        @Override
        public void handleMessage(Message msg) {

            ActionBar actionBar = myClassWeakReference.get();

            if (actionBar != null) {
                // ...do work here...
            }
        }
    }


    private Runnable disconnectCallback = new Runnable() {

        @Override
        public void run() {

            // Perform any required operation on disconnect

            Intent startActivity = new Intent(mContext, StartActivity.class);

            // Clear activity stack

            startActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

            startActivity(startActivity);
        }
    };

    public void resetDisconnectTimer() {

        mDisconnectHandler.removeCallbacks(disconnectCallback);
        mDisconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
    }

    public void stopDisconnectTimer() {

        mDisconnectHandler.removeCallbacks(disconnectCallback);
    }

    @Override
    public void onUserInteraction(){

        resetDisconnectTimer();
    }

    @Override
    public void onResume() {

        super.onResume();
        resetDisconnectTimer();
    }

    @Override
    public void onStop() {

        super.onStop();
        stopDisconnectTimer();
    }
}

补充资源

Android:清除活动堆栈

该处理程序类应该是静态的,否则可能发生泄漏


0

最好的办法是通过AppLifecycleCallbacks在应用程序calss中进行注册来处理整个应用程序(假设您有多个活动)。您可以registerActivityLifecycleCallbacks()在Application类中使用以下回调(我建议创建一个扩展ActivityLifecycleCallbacks的AppLifecycleCallbacks类):

public interface ActivityLifecycleCallbacks {
    void onActivityCreated(Activity activity, Bundle savedInstanceState);
    void onActivityStarted(Activity activity);
    void onActivityResumed(Activity activity);
    void onActivityPaused(Activity activity);
    void onActivityStopped(Activity activity);
    void onActivitySaveInstanceState(Activity activity, Bundle outState);
    void onActivityDestroyed(Activity activity);
}

0
open class SubActivity : AppCompatActivity() {
    var myRunnable:Runnable
    private var myHandler = Handler()

    init {
        myRunnable = Runnable{
            toast("time out")
            var intent = Intent(this, MainActivity::class.java)
            startActivity(intent)

        }
    }

    fun toast(text: String) {
        runOnUiThread {
            val toast = Toast.makeText(applicationContext, text, Toast.LENGTH_SHORT)
            toast.show()
        }
    }

   override fun onUserInteraction() {
        super.onUserInteraction();
        myHandler.removeCallbacks(myRunnable)
        myHandler.postDelayed(myRunnable, 3000)
    }

    override fun onPause() {
        super.onPause()
        myHandler.removeCallbacks(myRunnable)
    }

    override fun onResume() {
            super.onResume()
            myHandler.postDelayed(myRunnable, 3000)
    }
}

通过扩展您的活动

YourActivity:SubActivity(){}

当用户在YourActivity上经过3000毫秒后处于非活动状态时,进入MainActivity

我使用了先前的答案,并将其转换为kotlin。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.