iOS Question [B4XPages] How to lock app after period of inactivity

Andrew (Digitwell)

Well-Known Member
Licensed User
I am developing an app which contains some sensitive data.

I would like the app to lock out and require the user to re-enter their password to continue, in the following circumstances:

  1. When the user switches to another app or the homepage.
  2. After a period of inactivity (10 minutes)
I have solved 1 by using handling the B4xPages_background event.
Any suggestions how I could handle the second scenario. I have seen some comments about using timers which reset on user interaction, but I have nearly 30 B4xPages in this app with lots of UI controls, and I would prefer not to have to reset the timer in every click and textchanged etc event.

Note, when the screen timeouts, this also causes the B4xPages_background event to be fired. But I cannot guarantee that the user will have the screen timeout set.

Thanks
 

Erel

Administrator
Staff member
Licensed User
Not tested too much, based on: https://stackoverflow.com/a/5269900/971547

Add to main module, at the end:
B4X:
Public Sub ResetIdleTimer
    Log("Reset idle timer")
End Sub

#if OBJC
@end 
@interface B4IViewController (nextResponder)
@end
@implementation B4IViewController (nextResponder)
- (UIResponder *)nextResponder {
    [[b4i_main new].bi raiseEvent:nil event:@"resetidletimer" params:nil];
    return [super nextResponder];
}
#End If

Add a timer that counts every second and reset the counter in ResetIdleTimer.
 
Upvote 0

Andrew (Digitwell)

Well-Known Member
Licensed User
This works, but it seems to be called a lot.

Any screen that requires text entry has slowed to a crawl, in debug mode.

In release mode, all seems to be fine and performance does not seem any different to before.
 
Upvote 0

OliverA

Expert
Licensed User
Add a timer that counts every second
Could you also just create a timer with a interval of the timeout period (in this case 10 minutes) and then just do a
B4X:
Public Sub ResetIdleTimer
    Log("Reset idle timer")
    'Note: actual name of timer object may vary
    idleTimer.Enabled = False
    'The Sleep(0) is to let the system process the Enabled event. May not be needed. @Erel may chime in on this
    Sleep(0)
    idleTimer.Enabled = True
End Sub
to reset the timer? This way you would not have to use a 1 second resolution on the timer and keep track of counting.
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
Like an alternative it's possible to use classic sendEvent: (UIEvent *) event.

1) put main.m into Files/Special.
B4X:
#import <UIKit/UIKit.h>
#import "iCore.h"

int main (int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain (argc, argv, @"MyApplication", NSStringFromClass ([B4IAppDelegate class])); }}

2) At the end of main.module
B4X:
Sub ResetIdleTimer
    oldTime = DateTime.Now
End Sub

#If OBJC
@end
@interface MyApplication: UIApplication
@end
@implementation MyApplication
double oldTime = 0;
double newTime = 0;
- (void) sendEvent: (UIEvent *) event
  {
  newTime = [[NSDate date] timeIntervalSince1970];
  if (newTime - oldTime > 30)
     {
     oldTime = newTime;
     [[b4i_main new].bi raiseEvent:nil event:@"resetidletimer" params:nil];     
     };
  [super sendEvent: event];
  }
#End If

Because there is a lot of events and accuracy is not very important, objc rasises event not often than one time per 30 seconds (maybe another interval).

3) In Timer1_Tick (with interval, for example, 1 minute) an app compares current time (DateTime.Now) and oldTime variable. If difference is more than 10 minutes, means an app is inactivity.
 
Upvote 0

Erel

Administrator
Staff member
Licensed User
to reset the timer? This way you would not have to use a 1 second resolution on the timer and keep track of counting.
A 1 second timer doesn't have any effect on the app performance.

Your code will actually be much slower (though it will still be fast enough) as the event is raised many many times.

Because there is a lot of events and accuracy is not very important, objc rasises event not often than one time per 30 seconds (maybe another interval).
You are trying to solve a non-existent problem.
 
Upvote 0
Top