Auto logout after 15 minutes due to inactivity in android - android

How to use timer in android for auto logout after 15 minutes due to inactivity of user?
I am using bellow code for this in my loginActivity.java
public class BackgroundProcessingService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
timer = new CountDownTimer(5 *60 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
//Some code
//inactivity = true;
timer.start();
Log.v("Timer::", "Started");
}
public void onFinish() {
//Logout
Intent intent = new Intent(LoginActivity.this,HomePageActivity.class);
startActivity(intent);
//inactivity = false;
timer.cancel();
Log.v("Timer::", "Stoped");
}
};
return null;
}
}
and onclick of login button I have called intent for service.
Intent intent1 = new Intent(getApplicationContext(),
AddEditDeleteActivity.class);
startService(intent1);
Please advice......
This type of error message is shown after 15 mins

Use CountDownTimer
CountDownTimer timer = new CountDownTimer(15 *60 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
//Some code
}
public void onFinish() {
//Logout
}
};
When user has stopped any action use timer.start() and when user does the action do timer.cancel()

I am agree with Girish in above answer. Rash for your convenience i am sharing code with you.
public class LogoutService extends Service {
public static CountDownTimer timer;
#Override
public void onCreate(){
super.onCreate();
timer = new CountDownTimer(1 *60 * 1000, 1000) {
public void onTick(long millisUntilFinished) {
//Some code
Log.v(Constants.TAG, "Service Started");
}
public void onFinish() {
Log.v(Constants.TAG, "Call Logout by Service");
// Code for Logout
stopSelf();
}
};
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Add the following code in every activity.
#Override
protected void onResume() {
super.onResume();
LogoutService.timer.start();
}
#Override
protected void onStop() {
super.onStop();
LogoutService.timer.cancel();
}

First Create Application class.
public class App extends Application{
private static LogoutListener logoutListener = null;
private static Timer timer = null;
#Override
public void onCreate() {
super.onCreate();
}
public static void userSessionStart() {
if (timer != null) {
timer.cancel();
}
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if (logoutListener != null) {
logoutListener.onSessionLogout();
log.d("App", "Session Destroyed");
}
}
}, (1000 * 60 * 2) );
}
public static void resetSession() {
userSessionStart();
}
public static void registerSessionListener(LogoutListener listener) {
logoutListener = listener;
}
}
This App Class add into manifest
<application
android:name=".App"
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="#style/AppTheme">
<activity android:name=".view.activity.MainActivity"/>
</application>
Then Create BaseActivity Class that is use in whole applications
class BaseActivity extends AppCompatActivity implements LogoutListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
//setTheme(App.getApplicationTheme());
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
//Set Listener to receive events
App.registerSessionListener(this);
}
#Override
public void onUserInteraction() {
super.onUserInteraction();
//reset session when user interact
App.resetSession();
}
#Override
public void onSessionLogout() {
// Do You Task on session out
}
}
After that extend Base activity in another activity
public class MainActivity extends BaseActivity{
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

You can start a service and start a timer in it. Every 15 minutes, check if a flag, let's say inactivity flag is set to true. If it is, logout form the app.
Every time the user interacts with your app, set the inactivity flag to false.

you may need to create a BaseActivity class which all the other Activities in your app extend. in that class start your timer task (TimerTask()) in the onUserInteraction method:
override fun onUserInteraction() {
super.onUserInteraction()
onUserInteracted()
}
. The onUserInteracted class starts a TimerTaskService which will be an inner class for my case as below:
private fun onUserInteracted() {
timer?.schedule(TimerTaskService(), 10000)
}
The TimerTaskService class will be asfollows. Please note the run on UI thread in the case you want to display a DialogFragment for an action to be done before login the user out:
inner class TimerTaskService : TimerTask() {
override fun run() {
/**This will only run when application is in background
* it allows the application process to get high priority for the user to take action
* on the application auto Logout
* */
// val activityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
// activityManager.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_NO_USER_ACTION)
runOnUiThread {
displayFragment(AutoLogoutDialogFragment())
isSessionExpired = true
}
stopLoginTimer()
}
}
You will realise i have a stopTimer method which you have to call after the intended action has be envoked, this class just has timer?.cancel() and you may also need to include it in the onStop() method.
NB: this will run in 10 seconds because of the 10000ms

Use the build-in function called: onUserInteraction() like below:
#Override
public void onUserInteraction() {
super.onUserInteraction();
stopHandler(); //first stop the timer and then again start it
startHandler();
}

I hope this will help
I found it on github https://gist.github.com/dseerapu/b768728b3b4ccf282c7806a3745d0347
public class LogOutTimerUtil {
public interface LogOutListener {
void doLogout();
}
static Timer longTimer;
static final int LOGOUT_TIME = 600000; // delay in milliseconds i.e. 5 min = 300000 ms or use timeout argument
public static synchronized void startLogoutTimer(final Context context, final LogOutListener logOutListener) {
if (longTimer != null) {
longTimer.cancel();
longTimer = null;
}
if (longTimer == null) {
longTimer = new Timer();
longTimer.schedule(new TimerTask() {
public void run() {
cancel();
longTimer = null;
try {
boolean foreGround = new ForegroundCheckTask().execute(context).get();
if (foreGround) {
logOutListener.doLogout();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}, LOGOUT_TIME);
}
}
public static synchronized void stopLogoutTimer() {
if (longTimer != null) {
longTimer.cancel();
longTimer = null;
}
}
static class ForegroundCheckTask extends AsyncTask < Context, Void, Boolean > {
#Override
protected Boolean doInBackground(Context...params) {
final Context context = params[0].getApplicationContext();
return isAppOnForeground(context);
}
private boolean isAppOnForeground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List < ActivityManager.RunningAppProcessInfo > appProcesses = activityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
final String packageName = context.getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess: appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
return true;
}
}
return false;
}
}
}
Use above code in Activity as below :
public class MainActivity extends AppCompatActivity implements LogOutTimerUtil.LogOutListener
{
#Override
protected void onStart() {
super.onStart();
LogOutTimerUtil.startLogoutTimer(this, this);
Log.e(TAG, "OnStart () &&& Starting timer");
}
#Override
public void onUserInteraction() {
super.onUserInteraction();
LogOutTimerUtil.startLogoutTimer(this, this);
Log.e(TAG, "User interacting with screen");
}
#Override
protected void onPause() {
super.onPause();
Log.e(TAG, "onPause()");
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume()");
}
/**
* Performing idle time logout
*/
#Override
public void doLogout() {
// write your stuff here
}
}

Related

Infinite loop activity when using setRequestedOrientation() in API 19 (KitKat)

The 'setRequestedOrientation' method restarts the activity normally on any version of the android higher than Kitkat.
But in Kitkat, even using if, the activity continues to restart.
int orientation = getResources().getConfiguration().orientation;
// Doesn't work
if (orientation != ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
// Doesn't work
if (orientation != Configuration.ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
EDIT 1 - StackTrace:
https://gist.github.com/sshnakamoto/11ef6179a561054e54ec4d41a03238f0
Sorry, my log is too long to post here. I've created a gist. But essentially you will see a loop between onCreate() and onStart() methods.
EDIT 2 - ActivityCode:
public class TestActivity extends AppCompatActivity {
private static final String TAG = "TimerActivityCLONE";
private TextView textView;
private ConstraintLayout parentView;
private boolean isColorChanged;
private int textColor;
private int parentColor;
private Handler handler;
private Runnable runnable;
private Timer timer;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: started ");
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: super called ");
setContentView(R.layout.activity_timer);
Log.d(TAG, "onCreate: setContentView called ");
/* Find on layout*/
parentView = findViewById(R.id.parent);
textView = findViewById(R.id.textView);
textColor = Color.WHITE;
parentColor = Color.BLACK;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
private void initTimer() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
changeColors();
}
};
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
};
timer = new Timer();
timer.schedule(timerTask, 0, 1000);
}
private void changeColors() {
Log.d(TAG, "changeColors: size " + textView.getTextSize() / getResources().getDisplayMetrics().scaledDensity);
if (isColorChanged){
textView.setTextColor(parentColor);
parentView.setBackgroundColor(textColor);
isColorChanged = false;
} else {
textView.setTextColor(textColor);
parentView.setBackgroundColor(parentColor);
isColorChanged = true;
}
}
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
/* Start to show */
initTimer();
}
#Override
protected void onStop() {
super.onStop();
killTaskAndFinish();
}
#Override
public void onBackPressed() {
super.onBackPressed();
killTaskAndFinish();
}
private void killTaskAndFinish() {
/* Kill background Thread */
timer.cancel();
timer.purge();
handler.removeCallbacks(runnable);
/* Restore user screen orientation */
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
}
}
I've found the bug, it occurs when calling method killTaskAndFinish() inside onStop() due ResquestedOrientation() method restart activity.
But why does this loop only occur on Kitkat (emulator?)? Testing Lollipop it does not happen
I don't know why only occurs on KikKat, but I was able to fix removing handler use. Only TimerTask was need in my case.
This fixes that bug and prevent memory leaks.
#Override
protected void onStart() {
super.onStart();
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
changeColors();
}
});
}
};
timer = new Timer();
timer.schedule(timerTask, 0, speed);
}
#Override
protected void onStop() {
super.onStop();
timerTask.cancel();
timer.cancel();
timer.purge();
}

how to manage timer in a Service to run in background

I am Trying to Implement a service where when I a select a time, the timer starts and runs in the background. the thing is working fine. but when I select another time, the timer overlaps on one another. I want my app to work in such a way that different services should run for different time. also, when I kill the app and reopen it, I get the remaining time in all the services.
however my data is coming from a web service and this web service contains a field with time. when I click the time, the above concept should start.
I have implemented my code as,
BroadCastService.java
public class BroadCastService extends Service {
private long totalTimeCountInMilliseconds;
private long timeBlinkInMilliseconds;
private CountDownTimer countDownTimer;
private boolean blink;
String getTime;
public static final String COUNTDOWN_BR = "project.uop.assignment8";
Intent bi = new Intent(COUNTDOWN_BR);
public BroadCastService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
getTime = intent.getStringExtra("time");
setTimer();
startTimer();
Log.i("madhura","madhura");
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
}
private void setTimer() {
int time = 0;
//if (getTime.equals("")) {
time = Integer.parseInt(getTime);
// } else
/* Toast.makeText(BroadCastService.this, "Please Enter Minutes...",
Toast.LENGTH_LONG).show();*/
totalTimeCountInMilliseconds = 60 * time * 1000;
timeBlinkInMilliseconds = 30 * 1000;
}
private void startTimer() {
countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
#Override
public void onTick(long leftTimeInMilliseconds) {
long seconds = leftTimeInMilliseconds / 1000;
if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
if (blink) {
// mTextField.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
// mTextField.setVisibility(View.INVISIBLE);
}
blink = !blink;
}
String a = String.format("%02d", seconds / 60) + ":" + String.format("%02d", seconds % 60);
bi.putExtra("countdown", a);
sendBroadcast(bi);
}
#Override
public void onFinish() {
Toast.makeText(BroadCastService.this, "Finished", Toast.LENGTH_SHORT).show();
}
}.start();
}
}
and my TimerActivity.class
public class TimerActivity extends AppCompatActivity {
TextView mTextField;
TextView hotel;
private long totalTimeCountInMilliseconds;
private long timeBlinkInMilliseconds;
private CountDownTimer countDownTimer;
private boolean blink;
String getTime;
SessionManager sessionManager;
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
InitializeToolbar();
Intent in = getIntent();
getTime = in.getStringExtra("time");
Intent intent = new Intent(this,BroadCastService.class);
intent.putExtra("time",getTime);
this.startService(intent);
sessionManager = new SessionManager(this);
hotel = findViewById(R.id.textView);
hotel.setText(sessionManager.getUserName());
Log.i("started", "Started service");
mTextField = findViewById(R.id.timer);
}
public void InitializeToolbar(){
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle("Order Notification");
}
private BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateGUI(intent); // or whatever method used to update your GUI fields
}
};
#Override
public void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter(BroadCastService.COUNTDOWN_BR));
Log.i("efgh", "Registered broacast receiver");
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(br);
Log.i("abcd", "Unregistered broadcast receiver");
}
#Override
public void onStop() {
try {
unregisterReceiver(br);
} catch (Exception e) {
// Receiver was probably already stopped in onPause()
}
super.onStop();
}
#Override
public void onDestroy() {
stopService(new Intent(this, BroadCastService.class));
Log.i("Stopped", "Stopped service");
super.onDestroy();
}
private void updateGUI(Intent intent) {
if (intent.getExtras() != null) {
String millisUntilFinished = intent.getStringExtra("countdown");
mTextField.setText(millisUntilFinished);
}
}
}
thanks in advance.
Use Handler and #Overide its method Handler#handleMessage(Message msg)
See this: https://gist.github.com/mjohnsullivan/403149218ecb480e7759

Register opening and closing android app

How can I register when the user open and close my app? I want to register every opening and every closing.
Lifecycle methods for example onResume() are not effective because the app use multiple activitys.
I can't find anything about that.
the best way to check if the app is exited or run is like this:
public class MyApplication extends Application {
public static final String LOG_TAG = "MyApp";
public boolean wasInBackground = true;
private AppSession appSession;
private Timer mActivityTransitionTimer;
private TimerTask mActivityTransitionTimerTask;
private final long MAX_ACTIVITY_TRANSITION_TIME_MS = 2000; // Time allowed for transitions
Application.ActivityLifecycleCallbacks activityCallbacks = new Application.ActivityLifecycleCallbacks() {
#Override
public void onActivityResumed(Activity activity) {
if (wasInBackground) {
//Do app-wide came-here-from-background code
appEntered();
}
stopActivityTransitionTimer();
}
#Override
public void onActivityPaused(Activity activity) {
startActivityTransitionTimer();
}
...
};
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(activityCallbacks);
}
public void startActivityTransitionTimer() {
this.mActivityTransitionTimer = new Timer();
this.mActivityTransitionTimerTask = new TimerTask() {
public void run() {
// Task is run when app is exited
wasInBackground = true;
appExited();
}
};
this.mActivityTransitionTimer.schedule(mActivityTransitionTimerTask,
MAX_ACTIVITY_TRANSITION_TIME_MS);
}
public void stopActivityTransitionTimer() {
if (this.mActivityTransitionTimerTask != null) {
this.mActivityTransitionTimerTask.cancel();
}
if (this.mActivityTransitionTimer != null) {
this.mActivityTransitionTimer.cancel();
}
this.wasInBackground = false;
}
private void appEntered() {
Log.i(LOG_TAG, "APP ENTERED");
appSession = new AppSession();
}
private void appExited() {
Log.i(LOG_TAG, "APP EXITED");
appSession.finishAppSession();
// Submit AppSession to server
submitAppSession(appSession);
long sessionLength = (appSession.getT_close() - appSession.getT_open())/1000L;
Log.i(LOG_TAG, "Session Length: " + sessionLength);
}
The onCreate method for the application class only runs once when the application is started. Maybe extend the application class and create some logic?
Or if you just record the application opening in the onCreate method of your first activity?

continue service working when the application closes

I have a simple Service
public class UpdateService extends Service {
private int seconds;
final static String MY_ACTION = "MY_ACTION";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
timer.start();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
final CountDownTimer timer = new CountDownTimer(86400000, 1000) {
public void onTick(long millisUntilFinished) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
Intent intent = new Intent();
intent.setAction(MY_ACTION);
sendBroadcast(intent);
}
public void onFinish() { }
};
}
When I close an application service stops working. But showing that the service is running.
What am I doing wrong?
Update
I changed CountDownTimer to Thread, but the problem remained
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Util.saveInfo(getApplicationContext(), Util.SECONDS, seconds++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
OnStart()
if(!t1.isAlive())
t1.start();
Because CountDown Timer is working only foreground means app is running and not minimized or closed. You have to place a Thread in Service that executing at particular time of you want.
try this :
public class LocalService extends Service
{
private static Timer timer = new Timer();
private Context ctx;
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate()
{
super.onCreate();
ctx = this;
startService();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 5000);
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
System.out.println("test");
}
};
}

android - how can I stop the thread inside the service?

I have a checked button in my MainActivity. If that button is checked it should start the service but if a user unchecked the button I want to stop the service.
So in uncheck condition I have written this stopService(intentname); but the problem is the service is not stopping. Here is my code snippet:
Service Class
public class SimpleService extends Service
{
String selectedAudioPath = "";
private MyThread myythread;
public Intent intent;
public boolean isRunning = false;
long interval=30000;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
myythread = new MyThread(interval);
}
#Override
public synchronized void onDestroy()
{
super.onDestroy();
if(!isRunning)
{
myythread.interrupt();
myythread.stop();
isRunning = false;
}
}
#Override
public synchronized void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
if(!isRunning)
{
//this.intent = intent;
//System.out.println("the intent is" + intent);
myythread.start();
isRunning = true;
}
}
class MyThread extends Thread
{
long interval;
public MyThread(long interval)
{
this.interval=interval;
}
#Override
public void run()
{
while(isRunning)
{
System.out.println("Service running");
try
{
String myString = intent.getStringExtra("name");
if(myString == null)
Log.d("Service","null");
else
{
Log.d("Service","not null");
if(myString.equalsIgnoreCase("image"))
{
uploadImages();
Thread.sleep(interval);
}
else if(myString.equalsIgnoreCase("audio"))
{
uploadAudio();
Thread.sleep(interval);
}
}
}
catch (InterruptedException e)
{
isRunning = false;
e.printStackTrace();
}
}
}
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
Source: Stopping a thread inside a service
Don't use Threads. Use AsyncTask instead.
public class MyService extends Service {
private AsyncTask<Void,Void,Void> myTask;
#Override
public void onDestroy(){
super.onDestroy();
myTask.cancel(true);
}
#Override
public void onStart(Intent intent, int startid) {
myTask = new AsyncTask<Void,Void,Void>(){
#Override
public void doInBackground(Void aVoid[]){
doYourWorkHere();
}
}
myTask.execute();
}
}

Categories

Resources