My task is a call service in the RecyclerView when user click on switcher. My service is CountDownTimer work on background. And I dont know how call service from my holder.
I have error:
Non-static method 'startServiceTimer()' cannot be referenced from a
static contex
And I need to enable multiply countDownTimer`s in my service, can you help me with it?
My Holder
class SiteHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{
CardView cardView;
TextView sitename;
ImageView sitePhoto;
SwitchCompat switchNotify;
TextView textDate;
LinearLayout linearCard;
CountDownTimer t;
SiteHolder(View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.cardView);
sitename = itemView.findViewById(R.id.site_name);
sitePhoto = itemView.findViewById(R.id.site_photo);
switchNotify = itemView.findViewById(R.id.notificationSwitcher);
textDate = itemView.findViewById(R.id.textDate);
linearCard = itemView.findViewById(R.id.linearCard);
switchNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b){
t = new CountDownTimer(finish, tick) {...}.start(); //my local timer in recycler view
; MainActivity.startServiceTimer();
} else {
switchOff();
t.cancel();
}
}
});
startServiceTimer on MainActivity
protected void startServiceTimer(){
startService(new Intent(this, BroadcastService.class));
Log.d("BroadcastService", "Started service");
}
and my Service with random
public class BroadcastService extends Service {
private final static String TAG = "BroadcastService";
private final static String COUNTDOWN_BR = "package.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
private int cnt_service = 0;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Starting service timer...");
cnt_service++;
Log.d(TAG, "Count service = " + cnt_service);
cdt = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long l) {
Log.d(TAG, "Countdown timer seconds reamaning: " + l/1000);
bi.putExtra("countdown", l);
sendBroadcast(bi);
}
#Override
public void onFinish() {
Log.d(TAG, "FIRST timer finished.");
}
}.start();
}
#Override
public void onDestroy() {
cdt.cancel();
Log.d(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
cnt_service++;
Log.d(TAG, "Calling onStart command");
Log.d(TAG, "Count service = " + cnt_service);
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Sorry for this question, I am only learn this:)
You should implement Listener pattern here. Your activity will be listening to 'startTimer' event from recyclerview.
Do following:
First, declare Interface:
public interface TimerStarter {
void startTimer();
}
Pass this interface to yours RecyclerViewAdapter & ViewHolder consturctors and save it to local variable.
public class MyRvAdapter extends RecyclerViewAdapter<SiteHolder> {
private TimerStarter starter;
public MyRvAdapter(TimerStarter timerStarter) {
starter = timerStarter;
}
// Your code
// Do not forget to pass TimerStarter to SiteHolder via consturctor
}
class SiteHolder extends RecyclerView.ViewHolder implements
View.OnClickListener, View.OnLongClickListener{
... // Your fields
private TimerStarter starter;
SiteHolder(View itemView, TimerStarter timerStarter) {
starter = timerStarter;
}
// You can call starter.startTimer() where nesessary
}
Next, implement this interface in your activity
public class MainActivity extends Activity implements TimerStarter {
... // Your methods here
#Override
public void onCreate(Bundle savedInstanceState) {
... // Instructions
// this = TimerStarter
RecyclerViewAdapter adapter = new YourAdapter(this)
... // etc
}
#Override
public void startServiceTimer(){ // Make method public
startService(new Intent(this, BroadcastService.class));
Log.d("BroadcastService", "Started service");
}
... // Other methods
}
Related
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
I am running an android service. I wish to change a TextView text when I get expected result from the service. I have implemented an interface method to get a callback to change my textView. Interface abstract method runs well but cannot change the Textview text of my activity.
I have simplified sample code here
public class MainActivity extends Activity implements MyInterface {
TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.sample_text);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("Asim----", "Start service"); // print this line well
startService(new Intent(MainActivity.this, MyService.class));
}
});
}
#Override
public void testMe() {
Log.e("Asim----", "Hi"); // print this line well
mTextView.setText("New Text"); // Chrashes happens here
}
}
The MyService class here
public class MyService extends Service {
#Override
public void onCreate() {
//super.onCreate();
Log.e("test1------", "onCreate"); // print this line well
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("test2------", "onStartCommand"); // print this line well
MyInterface mi = new MainActivity();
mi.testMe();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
mTextView should be null you have to find it in this method
#Override
public void testMe() {
Log.e("Asim----", "Hi"); // print this line well
mTextView = (TextView) findViewById(R.id.sample_text);
mTextView.setText("New Text"); // Chrashes happens here
}
Try it once.
you need to pass Activity in your interface as well
#Override
public void testMe(Activity actvity) {
Log.e("Asim----", "Hi"); // print this line well
mTextView = (TextView) activity.findViewById(R.id.sample_text);
mTextView.setText("New Text"); // Chrashes happens here
}
This question already has answers here:
Call Activity method from adapter
(9 answers)
Closed 8 years ago.
I have a textview in a listview on clicking which it should perform some activity. Currently,I am writing onClick of textview inside getView method of custom adapter class. On click of textview , I am trigerring a method in my Activity class . But that Activity has that variable value as NULL eventhough its already been initialised in onCreate of Activity. Here's my code:
Adapter class:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
Item item = (Item) getItem(position);
TextView textView = (TextView) view
.findViewById(R.id.tv_song_title);
textView.setText(item.text);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity main = new MainActivity();
main.songPicked(pos); //calling act class method
}
});
Activity class:
private MusicService musicSrv;
public void songPicked(int position) { //method called
if (musicSrv!=null) //is null .Why??
{
musicSrv.setSong(position);
songName = musicSrv.playSong();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
songAdt = new SongAdapter();
songAdt.setRows(rows);
songView.setAdapter(songAdt);
playMusic();
}
public void playMusic() {
if (playIntent == null) {
playIntent = new Intent(this, MusicService.class);
startService(playIntent);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
}
}
// connect to the service
private ServiceConnection musicConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicBinder binder = (MusicBinder) service;
// get service
musicSrv = binder.getService();
// pass list
musicSrv.setList(songList);
musicBound = true;
Log.i("LEAKTEST", "Connected to instance " + this.toString());
}
#Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
musicSrv = null;
}
Use listeners instead of passing the whole activity.
The main idea is
public interface SmthListener() {
void onSmthHappens(smthParams);
}
public class WhoNotify {
SmthListener mListener;
public WhoNotify(SmthListener listener) {
mListener = listener;
}
public void smthHappensInMyClass() {
mListener.onSmthHappens(smthParams);
}
}
public class WhoListene implements SmthListener {
#Override
public void onCreate(...) {
... new WhoNotify(this);
}
#Override
void onSmthHappens(smthParams) {
// do stuff;
}
}
I'm writing a radio application, in which the user will be able to download some shows.
When the user click on a download button on the audio player, the show is added to the DB as a SavedShow.
The user can see the state of the SavedShow instances in a SavedShowsFragment, which shows a ListView with the list of the saved shows.
In each row of the ListView is the title of the saved show, its state (NOT_STARTED/DOWNLOADING/PAUSED/DOWNLOADED/ERROR), a ProgressBar and a Button to pause the download, resume it or play the file if it's downloaded.
Now I don't know how to bind each item of the list to my DownloadService nor how to implement listeners from DownloadService in the adapter.
Basically, I would like for each row to:
get the progress from the DownloadTask.onProgressUpdate of my DownloadService
be notified by the DownloadService when a download is finished or if there is an error
call methods from DownloadService (e.g. pause the download when clicking the button if the file is downloading)
Anybody could help?
SavedShowsFragment
public class SavedShowsFragment extends Fragment {
private DownloadService mDownloadService;
private boolean mBoundToDownloadService = false;
private ListView mListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.saved_show_list, container, false);
}
#Override
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
private void setSavedShowList(){
mListView = (ListView) getView().findViewById(R.id.listview);
SavedShowAdapter adapter = new SavedShowAdapter(getActivity(), MyApplication.dbHelper.getSavedShowList());
mListView.setAdapter(adapter);
}
#Override
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// start services
Intent intent = new Intent(getActivity(), DownloadService.class);
getActivity().startService(intent);
}
#Override
public void onResume() {
super.onResume();
setSavedShowList();
// bind service
Intent intent = new Intent(getActivity(), StreamService.class);
getActivity().bindService(intent, mDownloadServiceConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void onPause() {
// unbind service
if (mBoundToDownloadService) {
getActivity().unbindService(mDownloadServiceConnection);
}
super.onPause();
}
private ServiceConnection mDownloadServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
/*
* Get service instance
*/
DownloadServiceBinder binder = (DownloadServiceBinder) service;
mDownloadService = binder.getService();
mBoundToDownloadService = true;
/*
* Start download for NOT_STARTED saved show
*/
for(SavedShow savedShow : MyRadioApplication.dbHelper.getSavedShowList()){
if(savedShow.getState()==SavedShow.State.NOT_STARTED){
mDownloadService.downLoadFile(savedShow.getId());
}
}
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBoundToDownloadService = false;
}
};
}
SavedShowAdapter
public class SavedShowAdapter extends ArrayAdapter<SavedShow> {
private LayoutInflater mLayoutInflater;
static class ViewHolder {
TextView title, status;
ProgressBar progressBar;
Button downloadStateBtn;
}
public SavedShowAdapter(Context context, List<SavedShow> saved_show_list) {
super(context, 0, saved_show_list);
mLayoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
v = mLayoutInflater.inflate(R.layout.podcast_list_item, parent, false);
holder = new ViewHolder();
holder.title = (TextView)v.findViewById(R.id.title);
holder.status = (TextView)v.findViewById(R.id.status);
holder.progressBar = (ProgressBar)v.findViewById(R.id.progress_bar);
holder.downloadStateBtn = (Button)v.findViewById(R.id.btn_download_state);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.downloadStateBtn.setTag(position);
// TODO set button state according to item state
holder.downloadStateBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer) v.getTag();
// TODO call DownloadService method (download or pause) according to the state
}
});
//holder.title.setText(getItem(position).getTitle());
// do a publish progress listener for progress bar
return v;
}
}
DownloadService
public class DownloadService extends Service {
private static final int MAX_DOWNLOAD_TASKS = 10;
private final IBinder mBinder = new DownloadServiceBinder();
private class MaxDownloadsException extends Exception
{
private static final long serialVersionUID = 6859017750734917253L;
public MaxDownloadsException()
{
super(getResources().getString(R.string.max_downloads));
}
}
private List<DownloadTask> mTaskList= new ArrayList<DownloadTask>();
private void addTaskToList(DownloadTask task) throws MaxDownloadsException {
if(mTaskList.size() < MAX_DOWNLOAD_TASKS+1){
mTaskList.add(task);
}
else{
throw new MaxDownloadsException();
}
}
private void removeTaskToList(DownloadTask task) {
mTaskList.remove(task);
// if no more tasks, stop service
if(mTaskList.size() == 0){
stopSelf();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
/*
* Binding-related methods
*/
public class DownloadServiceBinder extends Binder {
DownloadService getService() {
return DownloadService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void downLoadFile(long savedShowId){
new DownloadTask().execute(savedShowId);
}
private class DownloadTask extends AsyncTask<Long, Integer, Void> {
private SavedShow savedShow;
private int contentLength;
#Override
protected Void doInBackground(Long... params) {
savedShow = MyApplication.dbHelper.getSavedShow(params[0]);
int contentLength;
HttpURLConnection connection = null;
BufferedInputStream in = null;
try {
URL url = new URL(savedShow.getUrl());
connection = (HttpURLConnection) url.openConnection();
long fileLength = new File(getFilesDir(), savedShow.getFilename()).length();
FileOutputStream outputStream = openFileOutput(savedShow.getFilename(), MODE_PRIVATE | MODE_APPEND);
int downloaded = 0;
contentLength = connection.getContentLength();
// If there is already a file with that filename,
// add 'Range' property in header
if(fileLength != 0){
connection.setRequestProperty("Range", "bytes=" + fileLength + "-");
}
in = new BufferedInputStream(connection.getInputStream());
//BufferedOutputStream out = new BufferedOutputStream(outputStream, 1024);
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
outputStream.write(data, 0, x);
downloaded += x;
publishProgress((int) (downloaded));
}
} catch (IOException e) {
MyApplication.dbHelper.updateSavedShowError(savedShow.getId(), e.toString());
}
finally{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
if(connection != null){
connection.disconnect();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// How can I pass values to SavedShowAdapter's items?
}
#Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
// TODO remove task
// How can I notify SavedShowAdapter's items?
}
}
}
Here's what I did:
to call DownloadService methods from the SavedShowAdapter, I passed the Service bound to the SavedShowFragment to the SavedShowAdapter.
to get DownloadService listeners in the Adapter, I set some BroadcastReceiver in the SavedShowFragment, which then call SavedShowAdapter's method that modify the data and call notifyDataSetChanged().
I see you're already binding to the service. You can inherit the default binder, and implement any methods you like on it, or create a messenger and send messages back and fourth. Both methods are explored in the API Guides, be sure to read through it and fully understand the advantages and disadvantages of each method:
http://developer.android.com/guide/components/bound-services.html
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
}
}