adMob iOS resume (back to app button) - ios

I have a little game with a timer.
I'm implementing adMob to monetize and I am not able to restart timer/ads after user clicks on the banner and come back to the app.
The flow is:
1 - game start
2 - show ads
3 - click on banner and pause timer
4 - oper safari
5 - click "back to my app" link/button (iOS feature)
6 - back to the app and restar timer (problem here)
I had implemented all adMob events method (and insert restar timer code) but I can't get out of this issue.
The code work because it worked with iAds (I'm migrating to adMob).
Any help is appreciated.
Thank you
EDIT:
here is the code:
/// Tells the delegate an ad request loaded an ad.
- (void)adViewDidReceiveAd:(GADBannerView *)adView {
NSLog(#"adViewDidReceiveAd");
self.pauseTimer = NO;
}
/// Tells the delegate an ad request failed.
- (void)adView:(GADBannerView *)adView
didFailToReceiveAdWithError:(GADRequestError *)error {
NSLog(#"adView:didFailToReceiveAdWithError: %#", [error localizedDescription]);
self.pauseTimer = NO;
}
/// Tells the delegate that a full screen view will be presented in response
/// to the user clicking on an ad.
- (void)adViewWillPresentScreen:(GADBannerView *)adView {
NSLog(#"adViewWillPresentScreen");
self.pauseTimer = NO;
}
/// Tells the delegate that the full screen view will be dismissed.
- (void)adViewWillDismissScreen:(GADBannerView *)adView {
NSLog(#"adViewWillDismissScreen");
self.pauseTimer = NO;
}
/// Tells the delegate that the full screen view has been dismissed.
- (void)adViewDidDismissScreen:(GADBannerView *)adView {
NSLog(#"adViewDidDismissScreen");
self.pauseTimer = NO;
}
/// Tells the delegate that a user click will open another app (such as
/// the App Store), backgrounding the current app.
- (void)adViewWillLeaveApplication:(GADBannerView *)adView {
NSLog(#"adViewWillLeaveApplication");
self.pauseTimer = YES;
}

In this VC create a property to store this
#property (nonatomic) BOOL didGoToSafari;
- (void)adViewWillLeaveApplication:(GADBannerView *)adView {
NSLog(#"adViewWillLeaveApplication");
self.pauseTimer = YES;
self.didGoToSafari = YES;
}
In the VC that you show right before the ad would show in viewWillAppear or viewDidAppear you should put this code
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(applicationDidBecomeActiveNotification:)
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
And then after viewDidAppear or viewWillAppear, write this function
- (void)applicationDidBecomeActiveNotification:(NSNotification *)notification {
if (self.didGoToSafari = YES){
self.pauseTimer = NO;
self.didGoToSafari = NO;
}
}
In viewWillDisappear
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
Basically what you're doing is listening to see if the app became active again. If it did, check to see if it's coming back from Safari. It's not perfect because you could feasibly be using the app, user goes to Safari and then doesn't go back to or close the game. They could then use Safari later and then go back to the game and it would start running again. There probably some control flow in the AppDelegate you could use to code around this, but in general this code should do it.
EDIT: As per your comment about understanding it, here's the full explanation.
You are using NSNotification to listen for when the app returns to an active state. UIApplicationDidBecomeActiveNotification is automatically called when your app becomes active (it's an app delegate method). When it does, the method (void)applicationDidBecomeActiveNotification gets called automatically and the methods in that method get called. You have a boolean flag to see if the app is returning from Safari because your app could return from any other app if user switched to another app when the ad got pushed. In the end, you remove your VC as an observer to avoid memory leaks.

Related

Call function when Notification Center is dismissed

I am just coding my first iOS app using a today widget (using Swift). I was wondering if there is a function that is called whenever my app comes back to the foreground after dismissing the notification center.
I know I can use an Observer to check for UIApplicationWillEnterForegroundNotification but my function does not get called when pulling down the notification center while using my app and dismissing it again.
My problem is simple:
It is quite unlikely users will pull down the notification center to manipulate data I am using in the app, but I still have to consider what happens if they do. The user is supposed to be able to save his current location by pressing the today widget button.
If that happens while using my app, the app won't check for new data.
I used the following code for determining if the notification center was opened during the application's run time:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
BOOL notificationCenterCurrentlyDisplayed;
}
- (void) viewDidLoad
{
[super viewDidLoad];
notificationCenterCurrentlyDisplayed = false;
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:#selector(onNotificationCenterDisplayed) name:UIApplicationWillResignActiveNotification object:nil];
[defaultCenter addObserver:self selector:#selector(onNotificationCenterDismissed) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void) onNotificationCenterDisplayed
{
notificationCenterCurrentlyDisplayed = true;
NSLog(#"Notification center has been displayed!");
}
- (void) onNotificationCenterDismissed
{
// Reason for this check is because once the app is launched the UIApplucationDidBecomeActiveNotification is called.
if (notificationCenterCurrentlyDisplayed)
{
notificationCenterCurrentlyDisplayed = false;
NSLog(#"Notification center has been dismissed!");
}
}
#end
Also the notification center was displayed method will also be called when the user decides to close the application into the background.

iAd freezes game's scene

I am developing a game using SpriteKit. I have iAds displayed in a view on the scene. When an ad in the Ad view is touched, the Ad appears, however, if I cross(X)/close the ad the scene in the game is frozen. I do not pause the scene or do anything on the events when the Ad appears and disappears. If I touch the ad again (now this is second time with frozen scene) and return to the scene, the scene un-freezes and everything starts to work as they were suppose to (strangely). I am not sure where is the problem in iAd or my app?
// Method is called when the iAd is loaded.
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
NSLog(#"Banner did load");
[self animateAdBanner];
}
-(void) animateAdBanner{
if(iAdsEnable){
[UIView animateWithDuration:6 delay:8
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
[self.adBanner setAlpha:0.85];
}
completion:^(BOOL finished){
if(finished){
//[self.adBanner setAlpha:0.7];
}
}];
}
}
According to Apple's ADBannerViewDelegate Protocol Reference:
bannerViewActionShouldBegin:willLeaveApplication:
If the willLeave parameter is YES, then your application is moved to the background shortly after this method returns. In this situation, your method implementation does not need to perform additional work. If willLeave is set to NO, then the triggered action will cover your application’s user interface to show the advertising action. Although your application continues to run normally, your implementation of this method should disable activities that require user interaction while the action is executing. For example, a game might pause its game play until the user finishes watching the advertisement.
Basically meaning that as your game is pushed into the background, the game will pause.
The delegate has a further method to notify you when the banner view has finished its action:
bannerViewActionDidFinish:
Discussion
If your delegate paused activities before allowing an action to run, it should resume those activities when this method is called.
It seems you can either use the above delegate methods to implement your own pause/un-pause or you could use the a NSNotification in your Scene to pause/un-pause when your app moves into the background and foreground respectively.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(pause)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(unPause)
name:UIApplicationWillEnterForegroundNotification
object:nil];
Sources:
iAd Framework Reference and ADBannerViewDelegate Protocol Reference

Manage iAd banner's touch while using iAdAdditions category

iOS 7 bring the iAdAdditions category to UIViewController.
With it managing a banner is a matter of one line of code:
self.canDisplayBannerAds = YES;
But I wonder how to detect user touching the iAd banner. My need is to pause game behaviors (music, animations, timers...) while iAd is displayed full screen.
I have tried the following code:
- (void) viewWillDisappear:(BOOL)animated {
if ([self isPresentingFullScreenAd]) {
// view will disappear because of user action on iAd banner
}
else {
// view will disappear for any other reasons
}
}
- (void) viewWillAppear:(BOOL)animated {
if ([self isPresentingFullScreenAd]) {
// view will appear because full screen iAd — caused by previous user action on iAd banner — is dismissed
}
else {
// view will appear for other reasons
}
}
I have done some testings showing everything is OK. But I wonder if it's the correct way to implement it!
UPDATE
This is the solution I use in the production version of the application and everything is fine: no problems has showned.
You can use these specific delegates in your view controller, here's code ripped straight from my game where I toggle the audio/music off when a banner is clicked.
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner
willLeaveApplication:(BOOL)willLeave
{
[[CPAudioManager sharedInstance] toggleOnOffDependingOnSettings];
return YES;
}
-(void)bannerViewActionDidFinish:(ADBannerView *)banner
{
[[CPAudioManager sharedInstance] toggleOnOffDependingOnSettings];
}
For full screen interstitials the code is roughly the same, but you don't get such nice delegates.
You know when you are showing a full screen ad when you call requestInterstitialAdPresentation and it returns YES, e.g.
if( [self requestInterstitialAdPresentation]==YES ) {...}
You should pause your views, toggle your music off, and kill your banner view (probably).
Then, you know when the user has closed the interstitial in ViewDidAppear
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if( self.isPresentingFullScreenAd )
{
// we are about to stop presenting full screen ads
// unpause view
// enable banner ads
// turn music back on if it was playing before
}
else
{
// we are presenting the normal view or the full screen ad
}
}

Multiple NSNotifications when screen rotates

I’m getting multiple UIKeyboardDidShowNotification and UIKeyboardDidHideNotification notifications when I rotate the device and I can’t figure out why.
I have an app that lets you edit the text for each picture. (It’s in a UITextView.) Most of the time I need to slide the text up so you can see it above the keyboard, then I slide it down when you are done editing. Then I do a database update to save the new text. I use notifications to tell me when the keyboard is displayed and when it goes away. It works fine on iPad when the user taps the keyboard close icon on the keyboard. It also works fine if the user swipes to the next page and iOS closes the keyboard. Since iPhones and iPods don’t have a keyboard close key, I wrote a method to close the keyboard when the picture or background is tapped. It works fine there too. However, when I rotate the device, I get multiple hide and show notifications. And I don’t know why.
Instead of getting one UIKeyboardDidHideNotification notification, I get a hide, a show, a hide, and then a show.
2:39:44.200 Picts for SLPs[16533:907] keyboardDidHide called. Keyboard showing flag is YES.
2:39:51.751 Picts for SLPs[16533:907] keyboardDidShow called. Keyboard showing flag is NO.
2:39:55.224 Picts for SLPs[16533:907] keyboardDidHide called. Keyboard showing flag is YES.
2:39:56.124 Picts for SLPs[16533:907] keyboardDidShow called. Keyboard showing flag is NO.
I posted the relevant code below. It is taken mostly from StackOverflow posts (Thanks guys).
In my class that displays the pictures I start notifications when it is initialized.
- (id)initWithParentView:(UIView *)parentview {
self = [super init];
if (self) {
_parentView = parentview;
if (ALLOW_DATABASE_EDITING) [self startNotifications];
}
return self;
}
- (void)startNotifications {
// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
}
The View Controller calls the hideKeyboard method in the View when the user taps on the picture.
- (void)dismissKeyboard {
if (self.showArtic.keyBoardIsShowing) {
[self.showArtic hideTheKeyboard];
}
}
resignFirstResponder sends a notification that closes the keyboard
- (void)hideTheKeyboard {
id <ShowArticDelegate> SA_delegate = _delegate;
// Don't update the database when there is no text.
if ( ![self.editableTextView.text isEqualToString:#""] ) {
[SA_delegate updateTextInDatabase:self.editableTextView.text];
}
[self.editableTextView resignFirstResponder];
}
These methods respond to the notifications.
- (void)keyboardDidHide:(NSNotification *)notification {
NSLog(#"keyboardDidHide called. Keyboard showing flag is %#.", self.keyBoardIsShowing ? #"YES" : #"NO");
self.keyBoardIsShowing = NO;
// Move the text, update the database
}
- (void)keyboardDidShow:(NSNotification *)notification {
NSLog(#"keyboardDidShow called. Keyboard showing flag is %#.", self.keyBoardIsShowing ? #"YES" : #"NO");
self.keyBoardIsShowing = YES;
// Move the text
}
any chance you could manually dismiss the keyboard and clean up your database from within this method:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
and then if you want the keyboard brought back up once the rotation completes, manually call your method to display it from within:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
That may or may not fit your needs, but it's a pretty common and clean technique to "get out of the way" while Apple handles the rotation, and then get back to business once everything is back on solid ground again.

How do I detect IOS app close and load only?

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.

Resources