My application after 30 seconds of doing nothing should came to the background. If there's no activity after 30 seconds, I want to log the user out. It's application which contains user interface. When the user want to back he must write again his username and password. I put below my code:
Timer.m:
#define kApplicationTimeoutInMinutes 0.1
#define kApplicationDidTimeoutNotification #"AppTimeOut"
#interface Timer : UIApplication
{
NSTimer *myidleTimer;
}
-(void)resetIdleTimer;
Timer.h:
#implementation Timer
//here we are listening for any touch. If the screen receives touch, the timer is reset
-(void)sendEvent:(UIEvent *)event
{
[super sendEvent:event];
if (!myidleTimer)
{
[self resetIdleTimer];
}
NSSet *allTouches = [event allTouches];
if ([allTouches count] > 0)
{
UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
if (phase == UITouchPhaseBegan)
{
[self resetIdleTimer];
}
}
}
//as labeled...reset the timer
-(void)resetIdleTimer
{
if (myidleTimer)
{
[myidleTimer invalidate];
}
//convert the wait period into minutes rather than seconds
int timeout = kApplicationTimeoutInMinutes * 60;
myidleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(idleTimerExceeded) userInfo:nil repeats:NO];
}
//if the timer reaches the limit as defined in kApplicationTimeoutInMinutes, post this notification
-(void)idleTimerExceeded
{
[[NSNotificationCenter defaultCenter] postNotificationName:kApplicationDidTimeoutNotification object:nil];
}
AppDelegate.m:
#implementation AppDelegate
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];
return YES;
}
-(void)applicationDidTimeout:(NSNotification *) notif
{
NSLog (#"time exceeded!!");
//This is where storyboarding vs xib files comes in. Whichever view controller you want to revert back to, on your storyboard, make sure it is given the identifier that matches the following code. In my case, "mainView". My storyboard file is called MainStoryboard.storyboard, so make sure your file name matches the storyboardWithName property.
UIViewController *viewController = [[UIStoryboard storyboardWithName:#"Main" bundle:NULL] instantiateViewControllerWithIdentifier:#"login"];
[(UINavigationController *)self.window.rootViewController pushViewController:viewController animated:YES];
}
//metoda, która informuje o przejsciu z aktywnego do nieaktywnego stanu
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
//- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
If I understand this correctly, you want a similar functionality to some password managers, which have a functionality of locking themselves after a certain period of time.
First, lets make clear that you cannot send the app to background on iOS. That is up to the user.
What you can do is lock the application after a certain period of time and display user and password prompt screen. To do this you need a timer (NSTimer), which gets restarted at every action by the user. If at any time timer gets to it's end - the 30 second interval passes, timer will execute your method, where you can display a modal view controller with user and password prompt. This way the app will stay locked until user enters username and password.
Detecting last action can also be done in multiple ways:
Detecting last user's touch
Adding few lines of code to all app actions
Swizzling navigation methods
...
Related
I'm new to make iPhone App with Objective-c
I want to make the App which sends a notification when iPhone screen is locked(Pressed Lock button)
How can I make this app?
I'm trying to make it using "applicationWillSuspend", but
/*----------------------------------------*/
- (void)applicationWillSuspend
{
NSLog(#"WillSuspend");
}
/*----------------------------------------*/
This code doesn't work
I'm not sure when applicationWillSuspend is called
Please, give me some knowledge
#import "AppDelegate.h"
#import <notify.h>
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// iOS8 Notification permit
if ([UIApplication
instancesRespondToSelector:#selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication]
registerUserNotificationSettings:[UIUserNotificationSettings
settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeSound
categories:nil]];
}
return YES;
int notify_token;
notify_register_dispatch("com.apple.springboard.lockstate",
¬ify_token,
dispatch_get_main_queue(),
^(int token)
{
uint64_t state = UINT64_MAX;
notify_get_state(token, &state);
if(state == 0) {
NSLog(#"unlock device");
} else {
NSLog(#"lock device");
}
}
);
}
Import this in app delegate #import <notify.h>
Write this piece of code in didFinishLaunchingWithOptions
int notify_token;
notify_register_dispatch("com.apple.springboard.lockstate",
¬ify_token,
dispatch_get_main_queue(),
^(int token)
{
uint64_t state = UINT64_MAX;
notify_get_state(token, &state);
if(state == 0) {
NSLog(#"unlock device");
} else {
NSLog(#"lock device");
}
}
);
So once your iPhone gets locked, you will get "lock device" as log. So you can write your code in that block. This will help you.
You can't do that on the iPhone.
But through, Darwin notifications. You can detect the event when the device is locked by "com.apple.springboard.lockcomplete".
Have a look at these links too hopefully it may help you:
1) Lock Unlock events iphone
2) How can I detect screen lock/unlock events on the iPhone?
applicationWillSuspend method doesn't exist natively, but in the AppDelegate.m you can play with applicationWillResignActive and applicationWillResignActive these methods will be called when the user hits the home button and the app will go to the background (here you can keep your connection live, but you should read the apple documentation regarding background tasks because your connection cannot be live forever if the app remains in the background. There are other ways to keep your app up to date like update on push notification etc):
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
and this method will be called when the app will get terminated (closed completely from multitasking).
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
You can handle your connections within these methods.
I have a messaging application and I want that the application listens the server on background and when new message comes, fires notification.
I tried to do that with timers and backgroundtasks, i can listen the server and the application fires the notification but when i reopen the application, i can not interact with anything, like the application is locked. Can you suggest any proper way to do that?
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sbCheckServerRecords) name:#"UIApplicationDidEnterBackgroundNotification" object:nil];
}
-(void) sbCheckServerRecords{
self.tmrCheckRecords = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:1] interval:10.0 target:self selector:#selector(sbCheckRecords) userInfo:nil repeats:YES];
[self.tmrCheckRecords fire];
}
-(void) sbCheckRecords{
#try{
if(any message comes)
notify user;
}
}
I have used timer as dispatch_source_t and
this class worked for me:
https://gist.github.com/maicki/7622108
I need show changes in external screen with UIImageView when my ios app is on background mode.
I use this code to change the UIImageView
campaingTimer = [NSTimer scheduledTimerWithTimeInterval:timeFirstAd target:self selector:#selector(changeImage) userInfo:nil repeats:NO];
This works when my app is active, but when in background, enters the changeImage method, but not change the picture.
NSTimer selectors are not guaranteed to fire off in the background. Unless you're registering for specific permissions, such as playing music in the background, and whatever you're actually doing in the background is directly related to the permission you asked for, you should work under the assumption you will not be able to execute code while the app is backgrounded, as that'll set you up to succeed much better than trying to find workarounds.
In this scenario, it seems like you want to change the image after so much time passes. That NSTimer you have (assuming your methods are written correctly) will work while the app is in the foreground, but to deal with background I recommend listening for the appDidEnterBackground and appWillEnterForeground and posting notifications (see sample code below).
AppDelegate.m
================
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.currentTime = [NSDate date];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationNameForBecameActive object:nil userInfo:#{kUserInfoForBecameActive: self.currentTime}];
}
================
ViewController.m
================
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didBecomeActive:) name:kNotificationNameForBecameActive object:nil];
}
- (void)didBecomeActive:(NSNotification *)notification
{
NSDate *sleepDate = notification.userInfo[kUserInfoForBecameActive];
NSTimeInterval secondsPassed = [[NSDate date] timeIntervalSinceDate:sleepDate];
if (secondsPassed >= timeFirstAd)
{
[self changeImage];
}
// reinitialize NSTimer
}
================
Alternatively, you could post notifications for both appDidEnterBackground and appWillEnterForeground and save the time there, along with invalidating your NSTimer and restarting it.
i know in iOS, if you leave your device idle for 45 seconds, the screen will become dim, if idle for another 15 seconds, the device will be locked automatically.
and we can disable the auto lock by
[UIApplication sharedApplication].idleTimerDisabled = YES
however, i do want this feature, just want to make it longer, is there any method (no jailbreak) that i can manually setup this timer?
thanks
You can achieve this to an extent by monitoring the user's interaction with your app (touch events) and setting [UIApplication sharedApplication].idleTimerDisabled = NO; when a custom idle timer expires.
You can learn more about monitoring events on this blog. However I've outlined the steps below with code updates for ARC.
A bit of background on what is possible after testing this. Apple's internal idle timer runs regardless if idleTimerDisabled = YES; is set. What this means is that if the user has not interacted with the phone past the Auto-Lock setting (i.e. 1 minute) when idleTimerDisabled = NO; is set the device will half dim immediately and turn off completely after 15 seconds. So what we can do is disable idleTimer, and manually create a new timer which waits x minutes before enabling the idleTimer again.
This will effectively allow you to increase the Auto-Lock time. I don't think you can decrease it (i.e. user has Auto-Lock Never, and you want to lock the device after a minute).
With the following code (assuming you have Auto-Lock set to 1 minute) the app will stay awake for 2 minutes, after which we set idleTimerDisabled = NO; dimming the app for 15 seconds before it turns off.
Add the following two files to your project (original source here):
ELCUIApplication.h
//
// ELCUIApplication.h
//
// Created by Brandon Trebitowski on 9/19/11.
// Copyright 2011 ELC Technologies. All rights reserved.
//
#import <Foundation/Foundation.h>
// # of minutes before application times out
#define kApplicationTimeoutInMinutes 2
// Notification that gets sent when the timeout occurs
#define kApplicationDidTimeoutNotification #"ApplicationDidTimeout"
/**
* This is a subclass of UIApplication with the sendEvent: method
* overridden in order to catch all touch events.
*/
#interface ELCUIApplication : UIApplication {
NSTimer *_idleTimer;
}
/**
* Resets the idle timer to its initial state. This method gets called
* every time there is a touch on the screen. It should also be called
* when the user correctly enters their pin to access the application.
*/
- (void)resetIdleTimer;
#end
ELCUIApplication.m
//
// ELCUIApplication.m
//
// Created by Brandon Trebitowski on 9/19/11.
// Copyright 2011 ELC Technologies. All rights reserved.
//
#import "ELCUIApplication.h"
#implementation ELCUIApplication
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
// Fire up the timer upon first event
if(!_idleTimer) {
[self resetIdleTimer];
}
// Check to see if there was a touch event
NSSet *allTouches = [event allTouches];
if ([allTouches count] > 0) {
UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
if (phase == UITouchPhaseBegan) {
[self resetIdleTimer];
}
}
}
- (void)resetIdleTimer {
if (_idleTimer) {
[_idleTimer invalidate];
// [_idleTimer release];
}
// Schedule a timer to fire in kApplicationTimeoutInMinutes * 60
float timeout = kApplicationTimeoutInMinutes * 60;
_idleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout
target:self
selector:#selector(idleTimerExceeded)
userInfo:nil
repeats:NO];
}
- (void)idleTimerExceeded {
/* Post a notification so anyone who subscribes to it can be notified when
* the application times out */
[[NSNotificationCenter defaultCenter]
postNotificationName:kApplicationDidTimeoutNotification object:nil];
}
//- (void) dealloc {
// [_idleTimer release];
// [super dealloc];
//}
#end
In your Supporting Files folder open up main.m, update the following:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, #"ELCUIApplication", NSStringFromClass([AppDelegate class]));
}
}
In AppDelegate.m edit the didFinishLaunchingWithOptions: method and add the applicationDidTimeout: method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[UIApplication sharedApplication].idleTimerDisabled = YES;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidTimeout:)
name:kApplicationDidTimeoutNotification object:nil];
return YES;
}
- (void) applicationDidTimeout:(NSNotification *) notif {
NSLog(#"applicationDidTimeout");
[UIApplication sharedApplication].idleTimerDisabled = NO;
}
I am trying to add some RevMob code into my app, the app currently has IAP in it and I am looking to add some advertising (fullscreen).
Now I currently have my code placed in the following method
- (void)applicationDidBecomeActive:(UIApplication *)application {
RevMobFullscreen *fullscreen;
fullscreen = [[RevMobAds session] fullscreen];
fullscreen.delegate = self;
[fullscreen loadAd];
[fullscreen showAd];
}
The problem is that this causes the advert to appear far too often. Ideally I only want to call the advert when the app first loads and then when the user closes the app and then reopens it (standby mode).
The above code is calling the advert code when the user also interacts with the IAP because the alert box is opened asking whether the user wants to buy.
Any Suggestions?
"Ideally I only want to call the advert when the app first loads and then when the user closes the app and then reopens it (standby mode)."
Implement the following methods of the UIApplicationDelegate:
application:didFinishLaunchingWithOptions:
As I'm sure you are well aware, this method fires once when the app is first launched. We have to implement this method because the following method is not called on first launch.
applicationWillEnterForeground:
From the documentation:
This method is called as part of the transition from the background to the active state.
This method is only called when the application moves from a background state. Unlike the applicationDidBecomeActive: method you were experiencing problems with applicationWillEnterForeground: is not called after brief interruptions such as dismissing an incoming SMS or phone call or interacting with In-App Purchases.
Code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[self showAd];
return YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[self showAd];
}
- (void)showAd
{
RevMobFullscreen *fullscreen;
fullscreen = [[RevMobAds session] fullscreen];
fullscreen.delegate = self;
[fullscreen loadAd];
[fullscreen showAd];
}
Use
application:didFinishLaunchingWithOptions:
for the initial launch of the app.
For the coming from backward feature record the date time like so
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.timeEnteredBackground = [NSDate date];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSDate* now = [NSDate date];
double diff = [now timeIntervalSinceDate:timeEnteredBackground];
if (diff > SOME_SECONDS)
This way the ad will only appear after a background time greater than some threshold.