title: App behaving differently over Mobile Data and Wifi
body: <p>I have an app to play online music. I have added code in that to detect a call and pause the music while on call and as soon as the call ends, it should again start the song. The problem is that it is behaving properly when the phone is connected via Wifi but not doing the same when connected over mobile data. How to make the song play again after call in Mobile Data as well.?</p>
  
  <p>Here is my code:</p>
  
  <p><strong>Reachability.m</strong></p>
  
  <pre><code>NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
  
  
  #pragma mark - Supporting functions
  
  #define kShouldPrintReachabilityFlags 1
  
  static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
  {
  #if kShouldPrintReachabilityFlags
  
      NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
            (flags &amp; kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',
  
            (flags &amp; kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
            (flags &amp; kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
            comment
            );
  #endif
  }
  
  
  static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
  {
  #pragma unused (target, flags)
      NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
      NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
  
      Reachability* noteObject = (__bridge Reachability *)info;
      // Post a notification to notify the client that the network reachability changed.
      [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
  }
  
  
  #pragma mark - Reachability implementation
  
  @implementation Reachability
  {
      BOOL localWiFiRef;
      SCNetworkReachabilityRef reachabilityRef;
  }
  
  
  + (instancetype)reachabilityWithHostName:(NSString *)hostName;
  {
      Reachability* returnValue = NULL;
      SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
      if (reachability != NULL)
      {
          returnValue= [[self alloc] init];
          if (returnValue != NULL)
          {
              returnValue-&gt;reachabilityRef = reachability;
              returnValue-&gt;localWiFiRef = NO;
          }
      }
      return returnValue;
  }
  
  
  + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
  {
      SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
  
      Reachability* returnValue = NULL;
  
      if (reachability != NULL)
      {
          returnValue = [[self alloc] init];
          if (returnValue != NULL)
          {
              returnValue-&gt;reachabilityRef = reachability;
              returnValue-&gt;localWiFiRef = NO;
          }
      }
      return returnValue;
  }
  
  
  
  + (instancetype)reachabilityForInternetConnection;
  {
      struct sockaddr_in zeroAddress;
      bzero(&amp;zeroAddress, sizeof(zeroAddress));
      zeroAddress.sin_len = sizeof(zeroAddress);
      zeroAddress.sin_family = AF_INET;
  
      return [self reachabilityWithAddress:&amp;zeroAddress];
  }
  
  
  + (instancetype)reachabilityForLocalWiFi;
  {
      struct sockaddr_in localWifiAddress;
      bzero(&amp;localWifiAddress, sizeof(localWifiAddress));
      localWifiAddress.sin_len = sizeof(localWifiAddress);
      localWifiAddress.sin_family = AF_INET;
  
      // IN_LINKLOCALNETNUM is defined in &lt;netinet/in.h&gt; as 169.254.0.0.
      localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
  
      Reachability* returnValue = [self reachabilityWithAddress: &amp;localWifiAddress];
      if (returnValue != NULL)
      {
          returnValue-&gt;localWiFiRef = YES;
      }
  
      return returnValue;
  }
  
  
  #pragma mark - Start and stop notifier
  
  - (BOOL)startNotifier
  {
      BOOL returnValue = NO;
      SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
  
      if (SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &amp;context))
      {
          if (SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
          {
              returnValue = YES;
          }
      }
  
      return returnValue;
  }
  
  
  - (void)stopNotifier
  {
      if (reachabilityRef != NULL)
      {
          SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
      }
  }
  
  
  - (void)dealloc
  {
      [self stopNotifier];
      if (reachabilityRef != NULL)
      {
          CFRelease(reachabilityRef);
      }
  }
  
  
  #pragma mark - Network Flag Handling
  
  - (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
  {
      PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
      BOOL returnValue = NotReachable;
  
      if ((flags &amp; kSCNetworkReachabilityFlagsReachable) &amp;&amp; (flags &amp; kSCNetworkReachabilityFlagsIsDirect))
      {
          returnValue = ReachableViaWiFi;
      }
  
      return returnValue;
  }
  
  
  - (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
  {
      PrintReachabilityFlags(flags, "networkStatusForFlags");
      if ((flags &amp; kSCNetworkReachabilityFlagsReachable) == 0)
      {
          // The target host is not reachable.
          return NotReachable;
      }
  
      BOOL returnValue = NotReachable;
  
      if ((flags &amp; kSCNetworkReachabilityFlagsConnectionRequired) == 0)
      {
          /*
           If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
           */
          returnValue = ReachableViaWiFi;
      }
  
      if ((((flags &amp; kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
          (flags &amp; kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
      {
          /*
           ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
           */
  
          if ((flags &amp; kSCNetworkReachabilityFlagsInterventionRequired) == 0)
          {
              /*
               ... and no [user] intervention is needed...
               */
              returnValue = ReachableViaWiFi;
          }
      }
  
      if ((flags &amp; kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
      {
          /*
           ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
           */
          returnValue = ReachableViaWWAN;
      }
  
      return returnValue;
  }
  
  
  - (BOOL)connectionRequired
  {
      NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
      SCNetworkReachabilityFlags flags;
  
      if (SCNetworkReachabilityGetFlags(reachabilityRef, &amp;flags))
      {
          return (flags &amp; kSCNetworkReachabilityFlagsConnectionRequired);
      }
  
      return NO;
  }
  
  
  - (NetworkStatus)currentReachabilityStatus
  {
      NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
      NetworkStatus returnValue = NotReachable;
      SCNetworkReachabilityFlags flags;
  
      if (SCNetworkReachabilityGetFlags(reachabilityRef, &amp;flags))
      {
          if (localWiFiRef)
          {
              returnValue = [self localWiFiStatusForFlags:flags];
          }
          else
          {
              returnValue = [self networkStatusForFlags:flags];
          }
      }
  
      return returnValue;
  }
  
  
  @end
  </code></pre>
  
  <p><strong>ViewController.m</strong></p>
  
  <pre><code>- (void)viewDidLoad
  {
  
      toggleIsOn=TRUE;
  
      MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:self.viewVolume.bounds] ;
  
      [self.viewVolume addSubview:volumeView];
  
      [volumeView sizeToFit];
      [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  
  }
  
  - (void)didReceiveMemoryWarning
  {
      [super didReceiveMemoryWarning];
  }
  
  -(IBAction)playButtonPressed:(id)sender
  {
  
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [defaults setBool:TRUE forKey:@"FirstPlay"];
      [defaults setBool:YES forKey:@"alertShown"];
  
          if(toggleIsOn)
          {
          if(noNetwork)
          {
              [self showAlert];
          }
          else
          {
          toggleIsOn=!toggleIsOn;
  
          player = nil;
          NSString *stringurl = @"";
          stringurl = @"http://something.pls";
          NSURL *url = [NSURL URLWithString:stringurl];
          asset = [AVURLAsset URLAssetWithURL:url options:nil];
          playerItem = [AVPlayerItem playerItemWithAsset:asset];
          player = [AVPlayer playerWithPlayerItem:playerItem];
          player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
          [playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:nil];
          [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
          [player play];
          isPlaying = TRUE;
          NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
          [center addObserver:self selector:@selector(audioSessionInterrupted:) name:AVAudioSessionInterruptionNotification object:nil];
  
          [self.toggleButton setImage:[UIImage imageNamed:@"reload.png"] forState:UIControlStateNormal];
          [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
          [[AVAudioSession sharedInstance] setActive: YES error: nil];
          [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
          }
          }
          else
          {
  
          [self.toggleButton setImage:[UIImage imageNamed:@"playMusic.png"] forState:UIControlStateNormal];
          self-&gt;player.rate=0.0;
          toggleIsOn=!toggleIsOn;
          isPlaying = FALSE;
      }
  
  
  }
  - (void)audioSessionInterrupted:(NSNotification *)notification
  {
  
      NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey];
      NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];
  
      switch (interruptionType.unsignedIntegerValue) {
          case AVAudioSessionInterruptionTypeBegan:{
             // [self.toggleButton setImage:[UIImage imageNamed:@"playMusic.png"] forState:UIControlStateNormal];
  
              // • Audio has stopped, already inactive
              // • Change state of UI, etc., to reflect non-playing state
          } break;
          case AVAudioSessionInterruptionTypeEnded:{
              // • Make session active
              // • Update user interface
              // • AVAudioSessionInterruptionOptionShouldResume option
              if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
                  // Here you should continue playback.
                  if(isPlaying)
                  {
                  [player play];
                  }
              }
          } break;
  
  
          default:
              break;
      }
  
  }
  
  
  - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)audioPlayer
  {
      if(isPlaying)
      {
          [player pause];
      }
  }
  -(void)audioRecorderEndInterruption:(AVAudioRecorder *)audioPlayer
  {
      if(isPlaying)
      {
          [player play];
  
      }
  }
  
  
  
  
  
  
  - (void)viewWillAppear:(BOOL)animated
  {
      [super viewWillAppear:animated];
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [defaults setBool:TRUE forKey:@"alertShown"];
      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
  
      internetReachable = [Reachability reachabilityForInternetConnection];
      [internetReachable startNotifier];
  
      // check if a pathway to a random host exists
      hostReachable = [Reachability reachabilityWithHostName:@"www.apple.com"];
      [hostReachable startNotifier];
  
  
  }
  
  - (void)viewDidAppear:(BOOL)animated
  {
      [super viewDidAppear:animated];
      [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
      [self becomeFirstResponder];
  }
  
  
  - (void)viewWillDisappear:(BOOL)animated
  {
      [super viewWillDisappear:animated];
      [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
      [self resignFirstResponder];
  }
  
  - (void)viewDidDisappear:(BOOL)animated
  {
      [super viewDidDisappear:animated];
  }
  
  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
      return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
  }
  
  
  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                          change:(NSDictionary *)change context:(void *)context {
  
      [playerItem removeObserver:self forKeyPath:keyPath];
  
  
      if ([keyPath isEqualToString:@"status"]) {
          AVPlayerItem *pItem = (AVPlayerItem *)object;
          if (pItem.status == AVPlayerItemStatusReadyToPlay)
          {
              metadatas.text = @"";
          }
      }
      if ([keyPath isEqualToString:@"timedMetadata"]) {
          for (AVAssetTrack *track in playerItem.tracks) {
              for (AVPlayerItemTrack *item in player.currentItem.tracks) {
                  if ([item.assetTrack.mediaType isEqual:AVMediaTypeAudio]) {
                      NSArray *meta = [playerItem timedMetadata];
                      for (AVMetadataItem *metaItem in meta) {
  
                          NSString *source = metaItem.stringValue;
                          metadatas.text = source;
                      }
                  }
              }
          }
      }
  
      [self.toggleButton setImage:[UIImage imageNamed:toggleIsOn ? @"playMusic.png" :@"stop.png"] forState:UIControlStateNormal];
  
  }
  
  -(IBAction) sliderChanged:(id)sender
  {
      player.volume = slider.value;
  
  }
  -(void) checkNetworkStatus:(NSNotification *)notice
  {
      // called after network status changes
      NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  
      switch (internetStatus)
      {
          case NotReachable:
          {
              NSLog(@"The internet is down.");
              NSLog(@"%d",[defaults boolForKey:@"alertShown"]);
              BOOL isAlertShown = [defaults boolForKey:@"alertShown"];
              if(isAlertShown)
             {
                 noNetwork = TRUE;
                 isPlaying = false;
                 [self showAlert];
             }
  
              break;
          }
          case ReachableViaWiFi:
          {
              NSLog(@"The internet is working via WIFI.");
              if(self.alert)
              {
                  [self.alert dismissWithClickedButtonIndex:0 animated:YES];
                  self.alert = nil;
              }
              noNetwork = FALSE;
  
              BOOL isFirstTimePlayed = [defaults boolForKey:@"FirstPlay"];
              if(!isPlaying)
              {
              if(isFirstTimePlayed)
              {
                  [self playButtonPressed:nil];
              }
              }
  
              break;
          }
          case ReachableViaWWAN:
          {
              NSLog(@"The internet is working via WWAN.");
              if(self.alert)
              {
                  [self.alert dismissWithClickedButtonIndex:0 animated:YES];
                  self.alert = nil;
              }
              noNetwork = FALSE;
  
              BOOL isFirstTimePlayed = [defaults boolForKey:@"FirstPlay"];
              if(!isPlaying)
              {
                  if(isFirstTimePlayed)
                  {
                      [self playButtonPressed:nil];
                  }
              }
  
              break;
          }
      }
  
     }
  
  
  -(void)showAlert
  {
      //NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      //[defaults setBool:FALSE forKey:@"alertShown"];
  
      //alert = [[UIAlertView alloc] initWithTitle: @"Alert" message: @"You have lost data connectivity. Please wait while we try to establish the connection again." delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
      //[alert show];
  
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [defaults setBool:FALSE forKey:@"alertShown"];
  
      self.alert = [[UIAlertView alloc] initWithTitle:@"Alert"
                                                                      message:@"You have lost data connectivity. Please wait while we try to establish the connection again."
                                                                     delegate:self
                                                            cancelButtonTitle:@"OK"
                                                            otherButtonTitles:nil];
      [self.alert show];
  }
  
  - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
  {
          if(!isPlaying)
          {
              [player pause];
              [self.toggleButton setImage:[UIImage imageNamed:@"playMusic.png"] forState:UIControlStateNormal];
          }
  }
  
  - (NSUInteger)supportedInterfaceOrientations{
      return UIInterfaceOrientationMaskPortrait;
  }
  
  
  
  
  @end
  </code></pre>