Bagaimana mendeteksi ketidakaktifan pengguna di Android

101

Pengguna memulai aplikasi saya dan masuk.
Pilih Batas Waktu Sesi menjadi 5 menit.
Melakukan beberapa operasi pada aplikasi. (semua di latar depan)
Sekarang Pengguna membawa Myapp ke latar belakang dan memulai beberapa aplikasi lain.
----> Penghitung waktu mundur dimulai dan pengguna logout setelah 5 menit
ATAU pengguna mematikan layar.
----> Penghitung waktu mundur dimulai dan pengguna logout setelah 5 menit

Saya ingin perilaku yang sama bahkan saat aplikasi berada di latar depan tetapi pengguna tidak berinteraksi dengan aplikasi untuk waktu yang lama, katakanlah 6-7 menit. Asumsikan layar AKTIF sepanjang waktu. Saya ingin mendeteksi jenis ketidakaktifan pengguna (Tidak ada interaksi dengan aplikasi meskipun aplikasi berada di latar depan) dan memulai penghitung waktu mundur saya.

Akh
sumber
1
Bisakah Anda selalu menjalankan pengatur waktu dan menyetel ulang setiap kali pengguna melakukan sesuatu?
Kyle P

Jawaban:

111

Saya menemukan solusi yang menurut saya cukup sederhana berdasarkan jawaban Fredrik Wallenius. Ini adalah kelas aktivitas dasar yang perlu diperluas oleh semua aktivitas.

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();
    }
}
gfrigon.dll
sumber
3
Ini akan membuat beberapa contoh dari Handlerdan Runnableuntuk masing-masing Activitydibuat. Jika kita mengubah dua anggota ini menjadi static, ini akan dihindari. Juga, bisa Anda ceritakan mengapa Anda menelepon stopDisconnectTimer()di onStop()`?
Gaurav Bhor
@Gaurav Dalam kasus saya, ini hanya diimplementasikan dalam satu aktivitas (oleh karena itu saya tidak menemukan masalah dengan staticpengubah). Adapun onStop(), dari apa yang saya ingat, saya panggil onBackPressed()untuk kembali ke layar login di callback putuskan yang pada gilirannya memanggil onStop()metode tersebut. Ketika pengguna kembali ke layar login secara manual, dengan menekan kembali, pengatur waktu harus dihentikan juga begitu juga stopDisconnectTimer()masuk onStop(). Saya kira bagian ini tergantung pada kebutuhan dan implementasi Anda.
gfrigon
@gfrigon apakah mungkin untuk mengarahkan pengguna ke aktivitas login?
Apostrofix
@Apostrifix, Tentu saja itu mungkin. Dalam kasus saya, hanya ada satu aktivitas: memanggil onBackPressed()vas secukupnya. Jika Anda memiliki lebih dari satu aktivitas di tumpukan, Anda hanya perlu membuat maksud untuk hal itu. Anda mungkin ingin melihat jawaban berikut untuk menghapus tugas Aktivitas (dan mencegah pengguna menyambung kembali di belakang): stackoverflow.com/questions/7075349/…
gfrigon
Kerja bagus! Saya menambahkan getter dan setter untuk runnable dan kemudian mengaturnya di kelas yang diperluas sesuai kebutuhan menggunakan metode onCreate ... sempurna, sekali lagi terima kasih.
CrandellWS
90

Saya tidak tahu cara melacak ketidakaktifan tetapi ada cara untuk melacak aktivitas pengguna. Anda bisa menangkap panggilan balik yang dipanggil onUserInteraction()dalam aktivitas Anda yang dipanggil setiap kali pengguna melakukan interaksi apa pun dengan aplikasi. Saya menyarankan melakukan sesuatu seperti ini:

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

Jika aplikasi Anda berisi beberapa aktivitas, mengapa tidak meletakkan metode ini dalam kelas super abstrak (memperluas Activity) dan kemudian meminta semua aktivitas Anda untuk memperluasnya.

Fredrik Wallenius
sumber
1
Ya, ini adalah salah satu cara untuk melakukannya ... tetapi aplikasi saya memiliki 30 aktivitas berbeda dan akan ada terlalu banyak interaksi saat pengguna aktif ... jadi setiap kali menyetel ulang pengatur waktu akan menjadi operasi yang mahal ... kasus terburuk bisa 50 sampai 60 kali dalam satu menit.
Akh
3
Saya belum mengatur waktunya tetapi saya akan mengatakan mengatur ulang pengatur waktu seperti ini lastInteraction = System.currentTimeMillis (); akan memakan waktu, katakanlah, 2 md. Lakukan 60 kali satu menit dan Anda "kehilangan" 120ms. Dari 60000.
Fredrik Wallenius
1
Fredrik ... Saya menggunakan saran Anda juga untuk memenuhi skenario ini .. Waktu tunggu layar disetel ke maksimal 30 menit pada perangkat. MyApp shd timeout setelah 15 menit ... Jika pengguna tidak menyentuh apa pun di layar dari lebih dari 1 menit maka saya akan memulai timer Logout 15 menit .... Dalam hal ini saya akan memeriksa differenct (lastInteractionTime dan System.currentTimeMills ( )) lebih dari 1 menit ... lalu tembak ..
Akh
3
onUserInteraction () tidak dipanggil dalam beberapa contoh namun (dialog tidak memanggilnya, dan menggulir di spinner) apakah ada solusi untuk situasi ini?
AndroidNoob
bisakah kamu membagikan MyTimerClass Anda?
Sibelius Seraphini
19

Saya pikir Anda harus menggunakan kode ini, ini untuk waktu tunggu sesi idle 5 menit: ->

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 
}
Pradeep Gupta
sumber
Anda menyelamatkan hidup saya dengan 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;
          }
        }
      }
    }

Logika isInForeGrnd ===> tidak ditampilkan di sini karena berada di luar cakupan pertanyaan

Anda dapat membangunkan kunci ke cpu dengan menggunakan kode perangkat di bawah ini-

  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);
      }
    }
Akh
sumber
4
@Nappy: Kalau begitu tolong jelaskan cara yang benar untuk melakukan ini. Komentar Anda tidak jelas dan bimbang.
Akh
2
@AKh: Jawaban lain sudah menunjukkan kemungkinan. Dalam solusi Anda, saya tidak melihat manfaat apa pun dari polling setiap 15 detik. Ini akan memiliki efek yang sama, saat Anda memulai pengatur waktu di "ACTION_SCREEN_OFF" dengan durasi acak dari 0-15 detik. Ini hanya tidak masuk akal ..
Popok
1
@Nappy: Setiap 15 detik saya tidak hanya memeriksa SCREEN_ON atau SCREEN_OFF tetapi juga untuk waktu interaksi terakhir pengguna dan status latar depan Aplikasi. Berdasarkan ketiga faktor ini, saya membuat keputusan logis tentang seberapa aktif pengguna berinteraksi dengan aplikasi.
Akh
Harap lengkapi komentar Anda. .... "jika isScreenof boolean Anda?" Dan juga status awal aplikasi harus diperhitungkan.
Akh
1
Kode ini penuh dengan kesalahan, beberapa variabel tidak diinisialisasi.
Big.Child
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));
}
soenke
sumber
Ini adalah dasar dari solusinya, sisanya dapat dimodifikasi tergantung pada kebutuhan partiular Anda dan kompleksitas arsitektur aplikasi! Terima kasih atas jawabannya!
Hack06
Cara menerapkan ini di kelas aplikasi
Gaju Kollur
6

Tidak ada konsep "pengguna tidak aktif" di tingkat OS, di luar siaran ACTION_SCREEN_OFFdan ACTION_USER_PRESENT. Anda harus mendefinisikan "ketidakaktifan" dalam aplikasi Anda sendiri.

CommonsWare
sumber
6

Bahkan Anda dapat mengelola kebutuhan Anda dengan @gfrigon atau @AKh solusi.

Tapi inilah solusi Timer dan Penangan gratis untuk ini. Saya sudah memiliki solusi Timer yang dikelola dengan baik untuk ini. Tetapi saya telah berhasil menerapkan solusi gratis Timer dan Handler.

Pertama saya memberi tahu Anda apa yang harus Anda kelola jika Anda menggunakan Timer atau Handlers.

  • Jika aplikasi Anda dimatikan oleh pengguna atau oleh pengoptimal, aplikasi Anda tidak akan pernah keluar secara otomatis, karena semua callback Anda dimusnahkan. ( Kelola beberapa Manajer atau Layanan Alarm? )
  • Apakah baik memiliki pengatur waktu di setiap kelas dasar? Anda membuat banyak utas hanya dengan menjalankan proses logout ( Kelola Penangan atau Timer statis di level aplikasi? ).
  • Bagaimana jika pengguna berada di latar belakang, Penangan Anda akan memulai Aktivitas Masuk jika pengguna melakukan pekerjaan lain di luar aplikasi Anda. ( Kelola latar depan atau latar belakang aplikasi? ).
  • Bagaimana jika layar mati secara otomatis. ( Kelola layar mati pada penerima siaran? )

Akhirnya saya menerapkan solusi yaitu

  1. NO Handler atau Timer.
  2. TIDAK ADA Manajer Alarm.
  3. TIDAK mengelola App LifeCycle.
  4. NO ACTION_SCREEN_ON/ ACTION_SCREEN_OFFPenerima Siaran.

Solusi Terpercaya termudah

Kami tidak akan mengamati ketidakaktifan pengguna berdasarkan pengatur waktu daripada kami akan memeriksa waktu aktivitas terakhir pada aktivitas pengguna. Jadi ketika pengguna berinteraksi aplikasi lain kali, saya memeriksa waktu interaksi terakhir.

Inilah BaseActivity.classyang akan Anda perluas dari setiap kelas aktivitas Anda, bukan LoginActivity. Anda akan menentukan waktu logout Anda di lapangan TIMEOUT_IN_MILLIdi kelas ini.

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.
    }
}
Khemraj
sumber
Bagaimana cara mengakses preferensi bersama di utas utama pada setiap interaksi pengguna lebih baik daripada memanggil banyak utas.
Nishita
@Nishita pada saat memposting jawaban ini, saya tidak menyadari kerugian ini. Terima kasih telah mengomentari 1 jawaban buruk saya. Anda benar, ini bukan cara yang tepat untuk melakukannya. Saya akan menyembunyikan jawaban ini.
Khemraj
2

Di kelas basis aktivitas saya, saya membuat kelas yang dilindungi:

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

Jadi dalam metode onResume - Anda dapat menentukan tindakan dalam callback Anda apa yang ingin Anda lakukan dengannya ...

idleTimer = new IdleTimer(60000, new IIdleCallback() {
            @Override
            public void inactivityDetected() {
                ...your move...
            }
        });
        idleTimer.startIdleTimer();
Dibagi nol
sumber
bagaimana cara memeriksa apakah pengguna tidak aktif ?? ada masukan dari sistem?
MohsinSyd
2

Selama Pencarian, saya menemukan banyak jawaban tetapi ini adalah jawaban terbaik yang saya dapatkan. Tetapi batasan dari kode ini adalah bahwa ia hanya berfungsi untuk aktivitas bukan untuk seluruh aplikasi. Ambil ini sebagai referensi.

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*/);
}

misalnya Anda menggunakan 8000, tugas akan dilakukan setelah 8 detik pengguna tidak aktif.

A_rmas
sumber
2

Ketidakaktifan pengguna dapat mendeteksi menggunakan onUserInteraction()metode penggantian di android

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

    }

Berikut adalah contoh kode, keluar (HomeActivity -> LoginActivity) setelah 3 menit saat pengguna tidak aktif

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

    }

}
damith alahakoon
sumber
2

Menangani pengguna dalam waktu tunggu interaksi di 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
}
Hitesh Sahu
sumber
1

Berikut adalah solusi lengkap yang Menangani ketidakaktifan pengguna setelah beberapa menit (mis. 3 menit). Ini memecahkan masalah umum seperti Aktivitas melompat ke latar depan saat Aplikasi berada di latar belakang saat waktu habis.

Pertama, kami membuat BaseActivity yang dapat diperluas oleh semua Aktivitas lainnya.

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

    }

}

Selanjutnya, kami membuat antarmuka untuk "Pemroses Logout" kami

package com.example.timeout;

public interface LogoutListener {

    void onSessionLogout();

}

Terakhir, kami membuat kelas Java yang memperluas "Aplikasi"

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


}

Catatan: Jangan lupa untuk menambahkan kelas "TimeOutApp" ke tag aplikasi Anda di dalam file manifes Anda

<application
        android:name=".TimeOutApp">
        </application>
Oyewo Remi
sumber
0

Saya rasa perlu dengan menggabungkan timer dengan waktu aktivasi terakhir.

Jadi seperti ini:

  1. Di onCreate (Bundle storedInstanceState) mulai pengatur waktu, katakanlah 5 menit

  2. Di onUserInteraction () cukup simpan waktu saat ini

Cukup sederhana sejauh ini.

Sekarang ketika timer pop melakukan seperti ini:

  1. Gunakan waktu saat ini dan kurangi waktu interaksi yang disimpan untuk mendapatkan timeDelta
  2. Jika timeDelta> = 5 menit, Anda sudah selesai
  3. Jika timeDelta <5 menit mulai pengatur waktu lagi, tapi kali ini gunakan 5 menit - waktu yang disimpan. Dengan kata lain, 5 menit merupakan interaksi terakhir
Robert Wiebe
sumber
0

Saya memiliki situasi yang mirip dengan pertanyaan SO, di mana saya perlu melacak ketidakaktifan pengguna selama 1 menit kemudian mengarahkan pengguna untuk memulai Aktivitas, saya juga perlu menghapus tumpukan aktivitas.

Berdasarkan jawaban @gfrigon saya datang dengan solusi ini.

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

Sumber daya pelengkap

Android: Hapus Tumpukan Aktivitas

Kelas Penangan ini harus statis atau kebocoran mungkin terjadi

chebaby
sumber
0

Hal terbaik adalah menangani ini di seluruh aplikasi Anda (dengan asumsi Anda memiliki banyak aktivitas) dengan mendaftar AppLifecycleCallbacksdi kals Aplikasi. Anda dapat menggunakan registerActivityLifecycleCallbacks()di kelas Aplikasi dengan callback berikut (saya sarankan membuat kelas AppLifecycleCallbacks yang memperluas ActivityLifecycleCallbacks):

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);
}
kotak
sumber
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)
    }
}

Perpanjang Aktivitas Anda dengan

YourActivity:SubActivity(){}

untuk masuk ke MainActivity saat Pengguna tidak aktif setelah 3000 milidetik di YourActivity

Saya menggunakan jawaban sebelumnya dan mengubahnya menjadi kotlin.

Tom Peak
sumber