iBeacon的使用
聽說可以通過iBeacon啟用IOS App,便研究了一下。
一、基本原理
iBeacon一般用於外設的,外設加入了iBeacon後,就會不斷廣播一定範圍的訊號。如果App加入了iBeacon的監聽,那麼如果App進入了外設的廣播範圍,那麼App裡面的iBeacon回撥就會有反應,也是通過這種方法啟用被掛起的App。因為我沒有嵌入了iBeacon的外設,這裡我是通過把mac改造成iBeacon外設,網上有個mac平臺的軟體:
https://github.com/timd/MactsAsBeacon
這軟體介面如下:
然後,看到這個介面你知道App怎麼初始化iBeacon了吧:
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:IBEACON_UUID];
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:2 minor:1000 identifier:[[NSBundle mainBundle] bundleIdentifier]];
二、IOS端IBeacon的開發
iBeacon的使用是基於藍芽和定位的,所以我這裡使用了許可權:(網上都說是需要基於藍芽的,但我測試過程中,把藍芽關閉了,也是可以的,但我還是加入了藍芽的許可權)
Location Always and When In Use Usage Description
Bluetooth Peripheral Usage Description
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>bluetooth-peripheral</string>
<string>location</string>
</array>
</plist>
App的程式碼部分:
@property(nonatomic) CLLocationManager *locationManager;
@property(nonatomic) CLBeaconRegion *beaconRegion;
- (CLLocationManager *)locationManager{
if(!_locationManager){
_locationManager = [[CLLocationManager alloc] init];
_locationManager.distanceFilter = 1.0f; //kCLDistanceFilterNone
_locationManager.delegate = self;
//控制定位精度,越高耗電量越
// _locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
return _locationManager;
}
- (CLBeaconRegion *)beaconRegion{
if(!_beaconRegion){
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:IBEACON_UUID];
// _beaconRegion = [[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier: [[NSBundle mainBundle] bundleIdentifier]];
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:2 minor:1000 identifier:[[NSBundle mainBundle] bundleIdentifier]];
_beaconRegion.notifyOnExit = YES;
_beaconRegion.notifyOnEntry = YES;
_beaconRegion.notifyEntryStateOnDisplay = YES;
}
return _beaconRegion;
}
//申請定位許可權並且開啟iBeacon監聽
- (void)startLocation{
CLAuthorizationStatus state = [CLLocationManager authorizationStatus];
if(state == kCLAuthorizationStatusNotDetermined){
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
[self.locationManager requestAlwaysAuthorization];
}
}
if(state == kCLAuthorizationStatusDenied){
NSString *message = @"您的手機目前未開啟定位服務,如欲開啟定位服務,請至設定開啟定位服務功能";
UIAlertController * ac = [UIAlertController alertControllerWithTitle:@"Tip" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * action1 = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
;
}];
[ac addAction:action1];
[self presentViewController:ac animated:YES completion:nil];
return;
}
if(state == kCLAuthorizationStatusRestricted){
NSString *message = @"定位許可權被限制";
UIAlertController * ac = [UIAlertController alertControllerWithTitle:@"Tip" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * action1 = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
;
}];
[ac addAction:action1];
[self presentViewController:ac animated:YES completion:nil];
return;
}
if( [CLLocationManager isMonitoringAvailableForClass:[self.beaconRegion class]] ) {
//開始定位
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
if (_beaconRegion && [CLLocationManager isRangingAvailable]) {
NSLog(@"startRangingBeaconsInRegion");
//開啟監聽
[_locationManager startRangingBeaconsInRegion:_beaconRegion];
}
}
iBeacon的各種回撥:
// delegate
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region{
_errorLab.text = @"didStartMonitoringForRegion";
WLlog(@"didStartMonitoringForRegion");
}
// 裝置進入該區域時的回撥
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
//App在後臺才會執行
self.view.backgroundColor = [UIColor redColor];
_errorLab.text = @"didEnterRegion";
WLlog(@"didEnterRegion");
}
// 裝置退出該區域時的回撥
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
//App在後臺才會執行
self.view.backgroundColor = [UIColor blackColor];
_errorLab.text = @"didExitRegion";
WLlog(@"didExitRegion");
}
// 有錯誤產生時的回撥
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(nullable CLRegion *)region withError:(NSError *)error{
_errorLab.text = @"monitoringDidFailForRegion";
}
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
NSString *proximity = @"unKnow";
CLBeacon *beacon = [beacons firstObject];
switch (beacon.proximity) {
case CLProximityImmediate:
{
// NSLog(@"very close");
proximity = @"very close";
}
break;
case CLProximityNear:
{
// NSLog(@"near");
proximity = @"near";
}
break;
case CLProximityFar:
{
// NSLog(@"far");
proximity = @"far";
}
break;
default:
{
NSLog(@"unKnow");
}
break;
}
proximity = [NSString stringWithFormat:@"%@\n%f meter\nrssi:%zi",proximity,beacon.accuracy,beacon.rssi];
_textLab.text = proximity;
// NSLog(@">>>>%f meter rssi:%zi",beacon.accuracy,beacon.rssi);
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region API_AVAILABLE(ios(7.0), macos(10.10)) API_UNAVAILABLE(watchos, tvos){
//第一次執行的時候,會走這裡,之後App在前臺的情況下,這裡就算狀態傳送改變了,也沒有執行。App在後臺才會執行
NSString *msg = @"didDetermineState";
if(state == CLRegionStateInside){
msg = @"Inside";
[[LocalNotifyManager sharedInstanced] pushLocalNotification:@"Tip" alertBody:msg flag:@"test" infoDic:nil];
[self checkAppLiveTime];
}
if(state == CLRegionStateOutside){
msg = @"Outside";
[[LocalNotifyManager sharedInstanced] pushLocalNotification:@"Tip" alertBody:msg flag:@"test" infoDic:nil];
[self checkAppLiveTime];
}
_errorLab.text = msg;
WLlog(msg);
}
很多人說didEnterRegion和didExitRegion都沒有執行,我測試過了,只有App進入到後臺時候,這兩個方法才有機會執行。
三、App後臺被啟用的時間
我使用了通知來測試後臺的啟用。App進入到後臺了,通知被啟用了,說明App確實被啟用了。
我接著測試了App被啟用的時間:
- (void)checkAppLiveTime{
//經過測試,每次App可有10秒左右的啟用時間,加上starBGTask後,可以存活幾分鐘
// [self starBGTask];
if(_liveTimer){
[_liveTimer invalidate];
_liveTimer = nil;
}
_liveTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
}
通過定時器,每秒寫入內容到檔案中。測試的結論是,啟用時間大概10秒左右。當然可以通過設定後臺任務讓時間延長一點,程式碼如下:
- (void)starBGTask {
if (_bgTask == UIBackgroundTaskInvalid) {
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"EndBackgroundTask");
bgTask = UIBackgroundTaskInvalid;
}];
_bgTask = bgTask;
}
}
相關文章
- ibeacon 技術記錄
- Scrapy框架的使用之Scrapyrt的使用框架
- ActiveMQ的使用及整合spring的使用例項MQSpring
- Docker框架的使用系列教程(四)容器的使用Docker框架
- Urllib庫的使用一---基本使用
- ECharts的使用Echarts
- DbVisualizer的使用
- Typeof的使用
- iview 的使用View
- Trait 的使用AI
- lombok的使用Lombok
- MybatisGenerator的使用MyBatis
- valueForKeyPath的使用
- ThreadLocal的使用thread
- elasticsearch的使用Elasticsearch
- CoreData的使用
- joomla的使用OOM
- sqlmap的使用SQL
- echars的使用
- SVG 的使用SVG
- FlowableAPI的使用API
- pycnblog的使用
- netcat的使用
- jextract的使用
- pinia的使用
- pip 的使用
- DBV 的使用
- Docker的使用Docker
- Promise的使用Promise
- SVN的使用
- EndNote的使用
- git的使用+Git
- git 的使用Git
- Bootstarp的使用boot
- GRPC的使用RPC
- Maven的使用Maven
- Scanner的使用
- @ModelAttribute 的使用