gpt4 book ai didi

ios - 应用程序在移动数据和 Wifi 上的行为不同

转载 作者:行者123 更新时间:2023-11-29 03:18:13 25 4
gpt4 key购买 nike

我有一个可以播放在线音乐的应用程序。我在其中添加了代码来检测调用并在通话时暂停音乐,并且一旦调用结束,它应该再次开始播放歌曲。问题是,当手机通过 Wifi 连接时它表现正常,但通过移动数据连接时却表现不佳。如何让移动数据通话后再次播放歌曲?

这是我的代码:

可达性.m

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 & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',

(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & 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->reachabilityRef = reachability;
returnValue->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->reachabilityRef = reachability;
returnValue->localWiFiRef = NO;
}
}
return returnValue;
}



+ (instancetype)reachabilityForInternetConnection;
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;

return [self reachabilityWithAddress:&zeroAddress];
}


+ (instancetype)reachabilityForLocalWiFi;
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;

// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);

Reachability* returnValue = [self reachabilityWithAddress: &localWifiAddress];
if (returnValue != NULL)
{
returnValue->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, &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 & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
{
returnValue = ReachableViaWiFi;
}

return returnValue;
}


- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// The target host is not reachable.
return NotReachable;
}

BOOL returnValue = NotReachable;

if ((flags & 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 & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
/*
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
*/

if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
/*
... and no [user] intervention is needed...
*/
returnValue = ReachableViaWiFi;
}
}

if ((flags & 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, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}

return NO;
}


- (NetworkStatus)currentReachabilityStatus
{
NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
NetworkStatus returnValue = NotReachable;
SCNetworkReachabilityFlags flags;

if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
if (localWiFiRef)
{
returnValue = [self localWiFiStatusForFlags:flags];
}
else
{
returnValue = [self networkStatusForFlags:flags];
}
}

return returnValue;
}


@end

ViewController.m

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

最佳答案

其实它不在你手里。这取决于您用于数据的 ISP。我使用 Tata Docomo 已经有一段时间了,大多数时候他们在调用电话后不会恢复互联网连接。这也取决于通话时间。如果它太短,您的应用程序将毫无问题地运行。他们可能正在维护一些数据 session 。所以,基本上我想告诉您的是,您在这里无能为力.. :(

关于ios - 应用程序在移动数据和 Wifi 上的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21427101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com