115

ユーザーがアプリを起動してログインします。[
セッション タイムアウト] を 5 分に選択します。
アプリでいくつかの操作を行います。(すべてフォアグラウンドで)
ここで、ユーザーは Myapp をバックグラウンドにして、他のアプリを起動します。
----> カウント ダウン タイマーが開始し、5 分後にユーザーをログアウトするか、
ユーザーが画面をオフにします。
----> カウント ダウン タイマーが開始し、5 分後にユーザーをログアウトします

アプリがフォアグラウンドにある場合でも同じ動作が必要ですが、ユーザーは6〜7分間アプリと長時間やり取りしません。画面が常にオンになっていると仮定します。ユーザーの非アクティブの種類(アプリがフォアグラウンドにあるにもかかわらず、アプリとの対話がない) を検出し、カウント ダウン タイマーを開始したいと考えています。

4

16 に答える 16

119

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();
    }
}
于 2012-09-18T17:18:05.257 に答える
104

非アクティブを追跡する方法はわかりませんが、ユーザー アクティビティを追跡する方法はあります。onUserInteraction()ユーザーがアプリケーションと対話するたびに呼び出される、アクティビティで呼び出されるコールバックをキャッチできます。次のようなことをお勧めします。

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

アプリに複数のアクティビティが含まれている場合は、このメソッドを抽象スーパー クラス (extending Activity) に配置してから、すべてのアクティビティでそれを拡張してください。

于 2010-11-17T23:11:03.370 に答える
11
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);
      }
    }
于 2010-11-18T00:15:58.727 に答える
6

ACTION_SCREEN_OFFおよびACTION_USER_PRESENTブロードキャストを超えて、OS レベルで「ユーザーの非アクティブ」という概念はありません。独自のアプリケーション内で何らかの形で「非アクティブ」を定義する必要があります。

于 2010-11-17T21:46:28.840 に答える
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();
于 2013-01-16T15:19:02.940 に答える
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 秒間操作を行わないとタスクが実行されます。

于 2016-03-23T08:49:41.493 に答える