Chromecast button not hiding - ios

I am using google casting through my app. It is working good but I am not able to hide the casting button when the cast device goes offline. It hides automatically but after a long time. How can I hide it immediately. Is there a way to get the notifications from the device scanner class.

You should try adding listener
[self.deviceScanner addListener:self];
[self.deviceScanner startScan];
#pragma mark - GCKDeviceScannerListener
- (void)deviceDidComeOnline:(GCKDevice *)device {
NSLog(#"device found!! %#", device.friendlyName);
[self updateCastIconButtonStates];
if ([self.delegate respondsToSelector:#selector(didDiscoverDeviceOnNetwork)]) {
[self.delegate didDiscoverDeviceOnNetwork];
}
}
- (void)deviceDidGoOffline:(GCKDevice *)device {
[self updateCastIconButtonStates];
}
Update
Similar Question.

Related

adMob iOS resume (back to app button)

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.

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
}
}

How to delay the prompt for location services permission

In my app I'm using CLLocationManager and MKMapView. When app launches, I present the user with a disclaimer (once) which has to be accepted. However, when the disclaimer is shown, a popup appears requesting access to the user location.
Is there a way to delay this alertView until the disclaimer is accepted?
Please advice.
EDIT:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if([[NSUserDefaults standardUserDefaults] objectForKey:#"disclaimerAccepted"] == nil) {
[self firstRun];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else
{
[self locationStuff];
}
)
The location alert view is only displayed when you actually request the user's location, so the simplest way to do this would be to ensure that the first time your app is run you start the CLLocationManager or display the MKMapView until after your disclaimer has been accepted. This may require you to move around some methods.
Maybe you need first check for disclaimer and if it accepted start CLLocationManager. If disclaimer not accepted - wait for acceptation and that start CLLocationManager.
- (void)viewDidLoad
{
[super viewDidLoad];
if (disclaimerAccepted)
{
//start CLLocationManager
}
else
{
//Show disclaimer
}
}
- (void)disclaimerAccepted
{
disclaimerAccepted = YES;
//start CLLocationManager
}

Hiding Ad view when no ad is received then showing again after

I have setup a test application using Admob Mediation service. I have an issue that when an error occurs and is handled by a method if I hide the banner View it causes no further ad requests to occur, possibly due to this 'hidden status'.
What I can do is sleep within the error method for a certain amount of time then request again, however this isn't the best method... I am guessing this would lock up some process and potentially other user input whilst sleepng? I am not sure of this as the app only includes ads so cannot test.
Here are my methods...
- (void)adView:(GADBannerView *)view didFailToReceiveAdWithError:(GADRequestError *)error;
{
NSLog(#"Failed to receive ad with error: %#", [error localizedFailureReason]);
bannerView_.hidden = YES;
sleep(59);
[bannerView_ loadRequest:[self createRequest]];
}
- (void)adViewDidReceiveAd:(GADBannerView *)view;
{
NSLog(#"Ad Received");
bannerView_.hidden = NO;
}
I am looking for the best way to either:
1. Hide the view when no ad is returned, but ensure requests continue and the ad view is shown again once an ad is received.
2. Use a loop in the error method to handle requesting again until successful and not locking up anything else.
Only being tested on simulator at the moment, if any difference is made.
I would suggest you to use performSelector to make an asynchronous call instead of using sleep because sleep will block your thread. So this is implemented as in the 1st way you mentioned.
- (void)adView:(GADBannerView *)view didFailToReceiveAdWithError:(GADRequestError *)error;
{
NSLog(#"Failed to receive ad with error: %#", [error localizedFailureReason]);
bannerView_.hidden = YES;
[self performSelector:#selector(repeatAdRequest) withObject:nil afterDelay:60.0];
}
- (void)adViewDidReceiveAd:(GADBannerView *)view;
{
NSLog(#"Ad Received");
bannerView_.hidden = NO;
}
-(void) repeatAdRequest
{
[bannerView_ loadRequest:[self createRequest]];
}
make addview a subview of another blank uiview.
In adview didfail, hide the view and not the adview
and in recieve show the view again.

How can I know users click fast forward and fast rewind buttons on the playback controls in iPhone

I want to implement the following things,
App is running a music or video (using MPMoviePlayerController) in background.
User double clicks the home button and go to the first screen showing playback controls (fast rewind, play or pause, fast forward buttons)
User click fast rewind or fast forward button.
Then app play previous or next music or video.
For the 3rd step, I should know which button is clicked.
(As I naturally know, the currently playing item is paused, stopped.. using MPMoviePlayerPlaybackStateDidChangeNotification notification).
Which notification should I register? Or are there any other approaches?
I got the answer by myself.
That is using UIApplication's beginReceivingRemoteControlEvents.
In an appropriate place (like viewWillAppear:) put the following code
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
And the view controller should implement the following method returning YES
- (BOOL)canBecomeFirstResponder {
return YES;
}
And then you can receive remote controller event in the following method.
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if( event.type == UIEventTypeRemoteControl ) {
NSLog(#"sub type: %d", event.subtype);
}
}
And event.subtype is as below,
typedef enum {
// available in iPhone OS 3.0
UIEventSubtypeNone = 0,
// for UIEventTypeMotion, available in iPhone OS 3.0
UIEventSubtypeMotionShake = 1,
// for UIEventTypeRemoteControl, available in iPhone OS 4.0
UIEventSubtypeRemoteControlPlay = 100,
UIEventSubtypeRemoteControlPause = 101,
UIEventSubtypeRemoteControlStop = 102,
UIEventSubtypeRemoteControlTogglePlayPause = 103,
UIEventSubtypeRemoteControlNextTrack = 104,
UIEventSubtypeRemoteControlPreviousTrack = 105,
UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
UIEventSubtypeRemoteControlEndSeekingBackward = 107,
UIEventSubtypeRemoteControlBeginSeekingForward = 108,
UIEventSubtypeRemoteControlEndSeekingForward = 109,
} UIEventSubtype;
This might be a very late answer, but as I notice, there aren't many Q/As about audio playing and remote controls, so I hope my answer helps the others who have the same problem:
I'm using AVAudioPlayer at the moment, but the remote controlling method which is - (void)remoteControlReceivedWithEvent:(UIEvent *)event must not be involved with the type of the player you're using.
To get the forward and rewind buttons on lock screen work, follow this:
In your view controller's viewDidLoad method add the following code:
//Make sure the system follows our playback status - to support the playback when the app enters the background mode.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
Then add these methods:
viewDidAppear:: (if not implemented already)
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Once the view has loaded then we can register to begin recieving controls and we can become the first responder
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
viewWillDisappear: (if not implemented already)
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//End recieving events
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
}
And:
//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl)
{
if (event.subtype == UIEventSubtypeRemoteControlPlay)
{
[self playAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlPause)
{
[self pauseAudio];
}
else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause)
{
[self togglePlayPause];
}
else if (event.subtype == UIEventSubtypeRemoteControlBeginSeekingBackward)
{
[self rewindTheAudio]; //You must implement 15" rewinding in this method.
}
else if (event.subtype == UIEventSubtypeRemoteControlBeginSeekingForward)
{
[self fastForwardTheAudio]; //You must implement 15" fastforwarding in this method.
}
}
}
This is working fine in my app, however if you want to be able to receive remote control events in all view controllers, then you should set it in the AppDelegate.
NOTE! This code is working fine at the moment, but I see two more subtypes called UIEventSubtypeRemoteControlEndSeekingBackward and UIEventSubtypeRemoteControlEndSeekingBackward. I'm not sure if they have to be implemented or not, if someone knows about it, let us know.

Resources