एंड्रॉइड में उपयोगकर्ता निष्क्रियता का पता कैसे लगाएं


101

उपयोगकर्ता मेरा ऐप शुरू करता है और लॉग इन करता है।
सत्र का समय 5 मिनट चुनें।
ऐप पर कुछ ऑपरेशन करता है। (सभी अग्रभूमि में)
अब उपयोगकर्ता Myapp को पृष्ठभूमि में लाते हैं और कुछ अन्य ऐप शुरू करते हैं।
----> 5 मिनट
या उपयोगकर्ता स्क्रीन बंद होने के बाद टाइमर डाउन गणना शुरू करता है और उपयोगकर्ता को लॉग आउट करता है।
----> टाइमर डाउन गणना शुरू होती है और 5 मिनट के बाद उपयोगकर्ता को लॉग आउट करता है

ऐप के अग्रभूमि में होने पर भी मैं ऐसा ही व्यवहार चाहता हूं, लेकिन उपयोगकर्ता 6-7 मिनट तक लंबे समय तक ऐप के साथ बातचीत नहीं करता है। मान लें कि स्क्रीन हर समय चालू है। मैं उपयोगकर्ता की निष्क्रियता का पता लगाना चाहता हूं (ऐप के साथ कोई बातचीत नहीं है, हालांकि ऐप अग्रभूमि में है) और किक डाउन टाइमर की शुरुआत करें।


1
क्या आपके पास हमेशा ऐसा टाइमर चल सकता है और जब भी उपयोगकर्ता कुछ करता है तो उसे रीसेट कर सकता है।
काइल पी

जवाबों:


112

मैं एक समाधान के साथ आया था जो मुझे फ्रेड्रिक वालीनियस के उत्तर के आधार पर काफी सरल लगता है। यह एक आधार गतिविधि वर्ग है जिसे सभी गतिविधियों द्वारा विस्तारित करने की आवश्यकता है।

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()? `
गौरव भोर

@ गौरव मेरे मामले में, यह केवल एक गतिविधि में लागू किया गया है (इसलिए मैं इस मुद्दे को staticसंशोधक के साथ नहीं पकड़ पाया )। जैसा कि onStop(), मुझे जो याद है, उसके लिए, मैं onBackPressed()डिस्कनेक्ट कॉलबैक में लॉगिन स्क्रीन पर लौटने के लिए कॉल करता हूं जो बदले में onStop()विधि को कॉल करता है। लॉगिन स्क्रीन पर उपयोगकर्ता रिटर्न मैन्युअल वापस दबाकर, टाइमर की जरूरत है अच्छी तरह से इस प्रकार के रूप में बंद कर दिया जाना करने के लिए जब stopDisconnectTimer()में onStop()। मुझे लगता है कि यह हिस्सा आपकी आवश्यकताओं और कार्यान्वयन पर निर्भर करता है।
gfrigon

@gfrigon क्या उपयोगकर्ता को लॉगिन गतिविधि में पुनर्निर्देशित करना संभव है?
Apostrofix

@Apostrifix, निश्चित रूप से यह संभव है। मेरे मामले में केवल एक गतिविधि थी: onBackPressed()पर्याप्त पुकार । यदि आपके स्टैक में एक से अधिक गतिविधियाँ हैं, तो आपको बस उस मामले के लिए एक इरादा बनाना होगा। गतिविधि कार्य को खाली करने के लिए (और उपयोगकर्ताओं को पीछे से जोड़ने से रोकने के लिए) निम्नलिखित उत्तर को देखना चाहते हैं: stackoverflow.com/questions/7075349/…
gfrigon

अच्छा कार्य! मैंने रनवेबल के लिए गेट्टर और सेटर को जोड़ा और फिर इसे एक्सट्रीमिंग क्लास में सेट किया जैसा कि ऑनक्रैट विधि का उपयोग करके आवश्यक है ... एकदम सही, फिर से धन्यवाद।
CrandellWS

90

मैं निष्क्रियता पर नज़र रखने का एक तरीका नहीं जानता, लेकिन उपयोगकर्ता गतिविधि को ट्रैक करने का एक तरीका है। आप onUserInteraction()अपनी गतिविधियों में बुलाए गए कॉलबैक को पकड़ सकते हैं जिसे हर बार उपयोगकर्ता द्वारा एप्लिकेशन के साथ कोई भी इंटरैक्शन करने के लिए कहा जाता है। मैं इस तरह से कुछ करने की सलाह दूंगा:

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

यदि आपके ऐप में कई गतिविधियाँ हैं, तो इस पद्धति को एक अमूर्त सुपर क्लास (विस्तारित Activity) में क्यों नहीं रखा गया है और फिर क्या आप सभी गतिविधियों को बढ़ा रहे हैं।


1
हाँ, यह इसे करने का एक तरीका है ... लेकिन मेरे ऐप में 30 अलग-अलग गतिविधियाँ हैं और उपयोगकर्ता के सक्रिय होने पर बहुत अधिक इंटरैक्शन होगा ... इसलिए हर बार टाइमर को रीसेट करना एक महंगा ऑपरेशन होगा ... सबसे खराब स्थिति एक मिनट में 50 से 60 बार हो सकती है।
अख

3
मैंने इसे समयबद्ध नहीं किया है, लेकिन मैं कहूंगा कि इस तरह के एक टाइमर को रीसेट करना होगा InInteraction = System.currentTimeMillis (); कहेंगे, 2 मि। इसे एक मिनट में 60 बार करें और आप 120 ग्राम "ढीला" करें। 60000 में से।
फ्रेड्रिक

1
फ्रेड्रिक ... मैं इस परिदृश्य को पूरा करने के लिए आपके सुझाव का उपयोग कर रहा हूं .. स्क्रीन टाइमआउट डिवाइस पर अधिकतम 30 मिनट के लिए सेट है। 15 मिनट के बाद MyApp shd टाइमआउट ... यदि उपयोगकर्ता 1 मिनट से अधिक समय तक स्क्रीन पर कुछ भी नहीं छूता है तो मैं 15min लॉगआउट टाइमर शुरू करूंगा .... इस मामले में मैं डिफरेंक्ट (lastInteractionTime और System.cnTimeTimeMills) की जांच करूंगा। )) 1 मिनट से अधिक है ... फिर आग ..
अख

3
onUserInteraction () को कुछ उदाहरणों में नहीं कहा जाता है, हालांकि (संवाद इसे नहीं कहते हैं, और स्पिनरों में स्क्रॉल करना) इन स्थितियों के लिए कोई काम है?
AndroidNoob

क्या आप अपना MyTimerClass साझा कर सकते हैं?
सिबेलियस सेराफिनी

19

मुझे लगता है कि आपको इस कोड के साथ जाना चाहिए, यह 5min निष्क्रिय सत्र टाइमआउट के लिए है: ->

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;
          }
        }
      }
    }

IsForeGrnd ===> तर्क यहाँ नहीं दिखाया गया है क्योंकि यह प्रश्न के दायरे से बाहर है

आप नीचे दिए गए डिवाइस कोड का उपयोग करके सीपीयू को लॉक जगा सकते हैं-

  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
@ नैपी: तो कृपया इसे करने का सही तरीका बताएं। आपकी टिप्पणी अस्पष्ट और अभद्र है।
अख

2
@ वाक: अन्य उत्तर पहले से ही संभावनाएं दिखाते हैं। आपके समाधान में, मुझे हर 15 सेकंड में मतदान से कोई लाभ नहीं दिखाई दे रहा है। इसका एक ही प्रभाव होगा, क्योंकि आप 0-15 सेकंड से यादृच्छिक अवधि के साथ "ACTION_SCREEN_OFF" पर टाइमर शुरू करते हैं। यह सिर्फ समझ में नहीं आता है ..
Nappy

1
@ नैपी: हर 15 सेकंड पर मैं न केवल SCREEN_ON या SCREEN_OFF की जांच करता हूं, बल्कि उपयोगकर्ता के अंतिम इंटरैक्शन समय और ऐप अग्रभूमि स्थिति के लिए भी। इन तीन कारकों के आधार पर मैं एक तार्किक निर्णय लेता हूं कि उपयोगकर्ता ऐप के साथ कितना सक्रिय है।
अख

कृपया अपनी टिप्पणी पूरी करें। .... "यदि आपका स्क्रीनस्क्रीन बूलियन है?" और ऐप के अग्रभाग की स्थिति को भी ध्यान में रखना होगा।
अख

1
यह कोड गलतियों से भरा है, कुछ चर आरंभिक नहीं हैं।
बिग.चिल्ड

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

आवेदन वर्ग में इसे कैसे लागू करें
गजु कोल्लूर

6

ओएस स्तर पर "उपयोगकर्ता निष्क्रियता" की कोई अवधारणा नहीं है, प्रसारण ACTION_SCREEN_OFFऔर ACTION_USER_PRESENTप्रसारण से परे है । आपको किसी भी तरह से अपने आवेदन के भीतर "निष्क्रियता" को परिभाषित करना होगा।


6

यहां तक ​​कि आप अपनी आवश्यकता को @gfrigon या @AK के साथ प्रबंधित कर सकते हैं समाधान के हैं।

लेकिन यहां टाइमर और हैंडलर इसके लिए मुफ्त समाधान है। मैंने पहले से ही इसके लिए टाइमर समाधान का प्रबंधन किया है। लेकिन मैंने टाइमर और हैंडलर मुक्त समाधान को सफलतापूर्वक लागू किया है।

पहले मैं आपको बताता हूं कि अगर आप टाइमर या हैंडलर का उपयोग करते हैं तो आपको क्या प्रबंधन करना है

  • यदि आपका ऐप उपयोगकर्ता द्वारा या किसी ऑप्टिमाइज़र द्वारा मार दिया जाता है, तो आपका ऐप कभी भी स्वचालित रूप से लॉगआउट नहीं होगा, क्योंकि आपके सभी कॉलबैक नष्ट हो जाते हैं। ( कुछ अलार्म मैनेजर या सेवा प्रबंधित करें? )
  • क्या हर आधार वर्ग में टाइमर होना अच्छा है? आप केवल लॉगआउट प्रक्रिया को लागू करने के लिए कई थ्रेड बना रहे हैं ( स्थैतिक हैंडलर या टाइमर को एप्लिकेशन स्तर पर प्रबंधित करें? ) के ।
  • यदि उपयोगकर्ता पृष्ठभूमि में है, तो आपका हैंडलर लॉगिन गतिविधि शुरू करेगा यदि उपयोगकर्ता आपके ऐप के बाहर कुछ अन्य काम कर रहा है। ( एप्लिकेशन अग्रभूमि या पृष्ठभूमि प्रबंधित करें? )।
  • क्या होगा अगर स्क्रीन अपने आप बंद हो जाती है। ( प्रसारण रिसीवर पर स्क्रीन बंद प्रबंधित करें? )

अंत में मैंने एक समाधान लागू किया जो है

  1. कोई हैंडलर या टाइमर।
  2. कोई अलार्म मैनेजर नहीं।
  3. App जीवन चक्र का प्रबंधन नहीं।
  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.
    }
}

प्रत्येक थ्रेड पर मुख्य थ्रेड पर साझा प्राथमिकताओं को एक्सेस करना किस प्रकार कई थ्रेड्स को लागू करने से बेहतर है।
निशिता

@ निशिता इस जवाब को पोस्ट करने के समय, मुझे इस असम्मान की जानकारी नहीं थी। मेरे 1 बुरे उत्तर पर टिप्पणी करने के लिए धन्यवाद। आप सही कह रहे हैं, यह करने का तरीका नहीं है। मैं इस उत्तर को छिपाऊंगा।
खेमराज

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();

उपयोगकर्ता कैसे निष्क्रिय है जाँच करने के लिए ?? सिस्टम से कोई इनपुट?
मोहसिनसाइड

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() एंड्रॉइड में ओवरराइड विधि

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

    }

उपयोगकर्ता द्वारा निष्क्रिय होने पर 3min के बाद यहाँ नमूना कोड, साइनआउट (होमएक्टिविटी -> 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

यहाँ एक पूर्ण समाधान है जो कुछ मिनटों (जैसे 3mins) के बाद उपयोगकर्ता निष्क्रियता को संभालता है। जब एप्लिकेशन समय-समय पर पृष्ठभूमि में होता है, तो यह गतिविधि जैसे सामान्य मुद्दों को अग्रभूमि में कूदता है।

सबसे पहले, हम एक BaseActivity बनाते हैं जिसे अन्य सभी गतिविधि विस्तारित कर सकती हैं।

यह 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();

}

अंत में, हम एक जावा क्लास बनाते हैं जो "एप्लिकेशन" का विस्तार करती है

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();
    }


}

नोट: "टाइमऑउटऐप" वर्ग को अपने मैनिफ़ेस्ट फ़ाइल के अंदर अपने एप्लिकेशन टैग में जोड़ना न भूलें

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

0

मुझे लगता है कि अंतिम सक्रियता समय के साथ टाइमर के संयोजन की आवश्यकता है।

तो इस तरह से:

  1. ऑनक्रिएट (बंडल सेवइनइंस्टेंसस्टेट) में 5 मिनट का कहना है कि एक टाइमर शुरू करें

  2. OnUserInteraction () में केवल वर्तमान समय संग्रहीत करें

अब तक बहुत सरल।

अब जब टाइमर पॉप इस तरह से:

  1. वर्तमान समय ले लो और संग्रहीत इंटरैक्शन समय को घटाकर टाइमडेलटा प्राप्त करें
  2. यदि समयडेल्टा है> = 5 मिनट, आप कर रहे हैं
  3. यदि समयडेल्टा है <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कि एप्लिकेशन कोल्स में रजिस्टर करके अपने पूरे ऐप (यह मानते हुए कि आपके पास कई गतिविधियाँ हैं) को संभालना है । आप registerActivityLifecycleCallbacks()निम्न कॉलबैक के साथ अनुप्रयोग वर्ग में उपयोग कर सकते हैं (मैं एक AppLifecycleCallbacks वर्ग बनाने की सलाह देता हूँ जो ActivLifecycleCallbacks का विस्तार करता है):

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(){}

जब आपकी निष्क्रियता पर 3000 मिलीसेक के बाद उपयोगकर्ता निष्क्रिय है तो मेनऐक्टिविटी पाने के लिए

मैंने पिछले उत्तर का उपयोग किया और इसे कोटलिन में बदल दिया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.