iOS App 后台运行
2016-03-28 11:04
441 查看
使用block的另一个用处是可以让程序在后台较长久的运行。在以前,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是应用可以调用UIApplication的beginBackgroundTaskWithExpirationHandler方法,让app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。APP进入后台时还能运行定时器的方法,应该会很有作用的。
让程序在后台长久运行的示例代码如下:
iOS的APP不是每一种类都可以进入后台或是说伪后台时还在执行代码的,想要能够在后台执行代码需要属于“App plays audio or streams audio/video using AirPlay”这三种类型的APP的才能实现。而且苹果针对这三类的APP审核也是比较严格的。在这里简单地介绍APP进入后台时还能运行定时器的方法,应该会很有作用的。
请参阅:
http://jingyan.baidu.com/article/d8072ac47d3c00ec94cefd5b.html
iOS的APP不是每一种类都可以进入后台或是说伪后台时还在执行代码的,想要能够在后台执行代码需要属于“App plays audio or streams audio/video using AirPlay”这三种类型的APP的才能实现。而且苹果针对这三类的APP审核也是比较严格的。在这里简单地介绍APP进入后台时还能运行定时器的方法,应该会很有作用的。
Mac OS X操作系统
Xcode编译器
新建一个empty(空的)工程项目。
在文件夹目录找到Info.plist文件,并打开。
在Info.plist文件中添加一行。
“key”键值滚动选择为“Required background modes”。
展开“Required background modes”的item,给“Item 0”的值输入“audio”,回车键,在iOS SDK8.0会显示为“App plays audio or streams audio/video using AirPlay”。
添加框架AVFoundation.framework。
打开AppDelegate.m文件进行配置
1、包含框架#import <AVFoundation/AVFoundation.h>;
2、设置允许后台运行;
3、添加定时器,这是可以让定时器停止运行,进入后台再启动;
4、在applicationDidEnterBackground方法添加代码,设置后台运行动作,并启动定时器;
5、实现定时器触发方法;
6、在APP恢复前台applicationDidBecomeActive时,停止定时器。
8
编译运行,按“home”键进入后台是将每秒计数1次,恢复前台,变活跃时,得到计数值。(完成)
iOS实现BLE后台持续连接外围设备(请参阅)
http://blog.shiqichan.com/ios-ble-background-central-scanning/
以下介绍iOS(iOS7)在后台BLE持续连接外围设备的开发步骤。
感谢Mario提供了完整的实现代码。我基本上是按照他的代码做介绍。
基本步骤是:
创建项目,设置plist
实现delegate方法,判断蓝牙状态,如成功则扫描指定UUID设备(如不指定UUID,则无法后台持续连接)
实现delegate方法,当发现指定设备后,连接该设备
实现delegate方法,当连接指定外围设备成功,编写定时器,每秒读取1次RSSI
实现delegate方法,当监听到失去和外围设备连接,重新建立连接
实现delegate方法,当读取到RSSI值,打印出它的值
创建一个Single View Application即可。
项目引入CoreBlue.framework。
代码中:
让ViewController实现相应的delegate:
下面就是实现delegate相关方法了。
代码:
其中f3d9是我连接到iPad mini2的LightBlue app模拟的BLE外围设备,你要换成你设备的UUID。
或者不设置具体的UUID:
貌似这样也可以,但是运行几分钟后,会出现类似这样的报错:
代码:
这里要注意,将peripheral对象设置给成员变量,保持对这个对象的引用,否则会因为没有引用计数而被回收。
代码:
这里创建了定时器(NSTimer),每间隔1秒读取1次RSSI,如果读到了就会触发peripheral的delegate方法,下面会说。
因为这个方法是iOS系统调用的,因此Timer是通过runloop跑在系统线程中的。
代码:
这个方法是必须实现的,因为我监控到,我的iPhone4S(Central)连接iPad mini2(Peripheral)大约每10秒钟就会中断连接,正好触发这个方法重建连接。
重建连接可能造成数秒后才能读取到RSSI。
代码:
这个方法读取到RSSI值,本示例中,基本上每秒读取到1次。
需要进一步测试,比如跑其他大应用,系统是否会停止BLE连接,这方面是否需要保持状态。
让程序在后台长久运行的示例代码如下:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// AppDelegate.h文件</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">assign</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) UIBackgroundTaskIdentifier backgroundUpdateTask; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// AppDelegate.m文件</span> - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)applicationDidEnterBackground:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> *)application { [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> beingBackgroundUpdateTask]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在这里加上你需要长久运行的代码</span> [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> endBackgroundUpdateTask]; } - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)beingBackgroundUpdateTask { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.backgroundUpdateTask</span> = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> endBackgroundUpdateTask]; }]; } - (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)endBackgroundUpdateTask { [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIApplication</span> sharedApplication] endBackgroundTask: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.backgroundUpdateTask</span>]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.backgroundUpdateTask</span> = UIBackgroundTaskInvalid; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>
iOS的APP不是每一种类都可以进入后台或是说伪后台时还在执行代码的,想要能够在后台执行代码需要属于“App plays audio or streams audio/video using AirPlay”这三种类型的APP的才能实现。而且苹果针对这三类的APP审核也是比较严格的。在这里简单地介绍APP进入后台时还能运行定时器的方法,应该会很有作用的。
请参阅:
http://jingyan.baidu.com/article/d8072ac47d3c00ec94cefd5b.html
iOS的APP不是每一种类都可以进入后台或是说伪后台时还在执行代码的,想要能够在后台执行代码需要属于“App plays audio or streams audio/video using AirPlay”这三种类型的APP的才能实现。而且苹果针对这三类的APP审核也是比较严格的。在这里简单地介绍APP进入后台时还能运行定时器的方法,应该会很有作用的。
工具/原料
Mac OS X操作系统Xcode编译器
方法/步骤
新建一个empty(空的)工程项目。在文件夹目录找到Info.plist文件,并打开。
在Info.plist文件中添加一行。
“key”键值滚动选择为“Required background modes”。
展开“Required background modes”的item,给“Item 0”的值输入“audio”,回车键,在iOS SDK8.0会显示为“App plays audio or streams audio/video using AirPlay”。
添加框架AVFoundation.framework。
打开AppDelegate.m文件进行配置
1、包含框架#import <AVFoundation/AVFoundation.h>;
2、设置允许后台运行;
3、添加定时器,这是可以让定时器停止运行,进入后台再启动;
4、在applicationDidEnterBackground方法添加代码,设置后台运行动作,并启动定时器;
5、实现定时器触发方法;
6、在APP恢复前台applicationDidBecomeActive时,停止定时器。
8
编译运行,按“home”键进入后台是将每秒计数1次,恢复前台,变活跃时,得到计数值。(完成)
iOS实现BLE后台持续连接外围设备(请参阅)
http://blog.shiqichan.com/ios-ble-background-central-scanning/
iOS实现BLE后台持续连接外围设备
以下介绍iOS(iOS7)在后台BLE持续连接外围设备的开发步骤。感谢Mario提供了完整的实现代码。我基本上是按照他的代码做介绍。
步骤简述
基本步骤是:创建项目,设置plist
实现delegate方法,判断蓝牙状态,如成功则扫描指定UUID设备(如不指定UUID,则无法后台持续连接)
实现delegate方法,当发现指定设备后,连接该设备
实现delegate方法,当连接指定外围设备成功,编写定时器,每秒读取1次RSSI
实现delegate方法,当监听到失去和外围设备连接,重新建立连接
实现delegate方法,当读取到RSSI值,打印出它的值
创建项目,设置plist
创建一个Single View Application即可。项目引入CoreBlue.framework。
代码中:
1 | #import <CoreBluetooth/CoreBluetooth.h> |
1 | @interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate> |
判断蓝牙状态
代码:12 | - (void)centralManagerDidUpdateState:(CBCentralManager *)central { DLog(); if (central.state == CBCentralManagerStatePoweredOn) { [self.centralManger scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"f3d9"]] options:nil]; } } |
或者不设置具体的UUID:
12 | - (void)centralManagerDidUpdateState:(CBCentralManager *)central { DLog(); if (central.state == CBCentralManagerStatePoweredOn) { [self.centralManger scanForPeripheralsWithServices:nil options:nil]; } } |
1 | 2014-01-02 11:10:40.799 BLEBackgroundMode[6961:60b] CoreBluetooth[WARNING] <CBPeripheral: 0x15d914a0 identifier = 730CF80B-90F6-C55C-3FB5-66326BDA453A, Name = "iPad", state = connecting> is not connected |
发现指定设备后连接该设备
代码:12 | - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { DLog(@"peripheral name %@ id %@ rssi %d", peripheral.name, peripheral.identifier, [RSSI integerValue]); self.peripheral = peripheral; [self.centralManger connectPeripheral:peripheral options:nil]; } |
连接指定外围设备后启动读取RSSI定时器
代码:12 | - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { DLog(); self.peripheral.delegate = self; if (!self.timer) { self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(readRSSI) userInfo:nil repeats:1.0]; [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode]; } } |
因为这个方法是iOS系统调用的,因此Timer是通过runloop跑在系统线程中的。
失去和外围设备连接后重建连接
代码:12 | - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { [self.centralManger connectPeripheral:peripheral options:nil]; } |
重建连接可能造成数秒后才能读取到RSSI。
读取到RSSI值后的操作
代码:12 | - (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error { if (!error) { NSLog(@"rssi %d", [[peripheral RSSI] integerValue]); } } |
存在的问题
需要进一步测试,比如跑其他大应用,系统是否会停止BLE连接,这方面是否需要保持状态。
相关文章推荐
- Xcode使用Archive打包,一直在读取iOS Apps,导致速度太慢的解决办法
- Android中ListView.getCount()与ListView.getChildCount()区别和OnScrollListener()各个参数的区别
- iOS开发--传感器
- 初涉RxAndroid结合Glide实现多图片加载操作
- 【Android和Unity交互】Android SDK下载速度慢无法更新?使用国内镜像站加速!
- 初涉RxAndroid结合Glide实现多图片加载操作
- 自定义scrollView实现顶部图片下拉放大
- Android surfaceView 与View 的区别分析
- 深入浅出Swift的Optional ?!
- android自定义大括弧
- javascript下用ActiveXObject控件替换word书签,将内容导出到word后打印第1/2页
- 一步一步实现iOS微信自动抢红包
- [Cocos2d-x v3.x官方文档]纹理缓存
- iOS证书申请教程
- 调用系统应用选择联系人并返回联系人信息
- Binary XML file line #8: Error inflating class android.support.design.widget.NavigationView
- Android NDK R9
- 移动端6种导航设计总结
- 玩转iOS卡片布局
- [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍