由于项目需要,app与服务器之间需要保持一个常交互的关系。最好是app打开一次之后,在不主动杀死app的情况下,依然能与服务器交互数据。有以下几个方案:
1、GPS定位:通过一直获取地理信息,类似于百度地图的导航功能,该方法基本可以达到目的。但是受限于很多人不一定开启位置服务,而且该方法会导致耗电很快,最终没有采用。
2、音乐播放:这个就比较简单了,app中循环播放一段无声的音频,但是在锁屏状态下时会显示player界面,而且无法通过自定义移除这个界面。肯定不行也是没有采用。
3、VOIP:钉钉、QQ、微信的语音通话就是通过这个来达到不开启app情况下,唤醒接电话界面。原理就是通过voip提供的推送协议,在每次静默推送的情况下app内接受到推送消息,会给出大概10秒钟时间处理事件。通过此10s时间可以对数据进行处理和服务器交互。而且该方法可以在app杀掉进程,手机重启之后唤醒app。最后服务器可以定时几分钟给每个用户推送一次,定时唤醒app,达到心跳机制。这就是我们想要的方法。
开源代码:
源码里是第三种实现方案,如果有朋友需要前面2种的实现代码。可以在github上issues我,或者在文章后面评论,后续再补上。
补上另外2种方式的大概代码:
1:音乐播放#import@interface AppDelegate () { UIBackgroundTaskIdentifier _bgTaskId; AVAudioPlayer *avAudioPlayer; }@property (assign, nonatomic) UIBackgroundTaskIdentifier bgTask;@property (assign, nonatomic) BOOL played; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; //开启后台处理多媒体事件 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; AVAudioSession *session = [AVAudioSession sharedInstance]; [session setActive:YES error:nil]; //后台播放 [session setCategory:AVAudioSessionCategoryPlayback error:nil]; _bgTaskId = [AppDelegate backgroundPlayerID:_bgTaskId]; [self playmusic]; [self configNowPlayingCenter];+(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId{ //设置并激活音频会话类别 AVAudioSession *session=[AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; //允许应用程序接收远程控制 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; //设置后台任务ID UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid; newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; if(newTaskId != UIBackgroundTaskInvalid && backTaskId != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:backTaskId]; } return newTaskId;}//处理中断事件-(void)handleInterreption:(NSNotification *)sender{ if(_played) { [avAudioPlayer pause]; _played = NO; } else { [avAudioPlayer play]; _played = YES; }}-(void)playmusic{ //从budle路径下读取音频文件 这个文件名是你的歌曲名字,mp3是你的音频格式 NSString *string = [[NSBundle mainBundle] pathForResource:@"李玉刚 - 刚好遇见你" ofType:@"mp3"]; //把音频文件转换成url格式 NSURL *url = [NSURL fileURLWithPath:string]; //初始化音频类 并且添加播放文件 avAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; //设置代理 avAudioPlayer.delegate = self; //设置初始音量大小 avAudioPlayer.volume = 1; //设置音乐播放次数 -1为一直循环 avAudioPlayer.numberOfLoops = -1; //预播放 // [avAudioPlayer play];}-(void)configNowPlayingCenter { [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:nil];}2:GPS定位@property (strong, nonatomic) NSTimer *timer; LocationManager *locationManager;- (void)initLocation{ locationManager = [LocationManager shareInstance]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"定位服务当前可能尚未打开,请设置打开!"); return; } //如果没有授权则请求用户授权 if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined){ [locationManager._locationManager requestAlwaysAuthorization]; }else if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorizedAlways){ //设置代理 locationManager._locationManager.delegate = self; // //设置定位精度 // _locationManager.desiredAccuracy=kCLLocationAccuracyBest; // //定位频率,每隔多少米定位一次 // CLLocationDistance distance= 0;//十米定位一次 // _locationManager.distanceFilter=distance; //启动跟踪定位 [locationManager._locationManager startUpdatingLocation]; }}#pragma mark CLLocationManagerDelegate-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *location=[locations firstObject];//取出第一个位置 CLLocationCoordinate2D coordinate=location.coordinate;//位置坐标 NSLog(@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed); if (_timer == nil) { _timer = [NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:@selector(activeLog) userInfo:nil repeats:YES]; }}复制代码