在上一篇文章《iOS藍(lán)牙4.0收發(fā)數(shù)據(jù)設(shè)計(jì)》,有簡(jiǎn)單的介紹收發(fā)數(shù)據(jù)設(shè)計(jì)。
在iOS藍(lán)牙4.0開發(fā)過(guò)程中褐捻,肯定還有許多伙伴痪宰,會(huì)遇到監(jiān)聽(tīng)后臺(tái)來(lái)電的需求。
那么iOS下匆光,如果監(jiān)聽(tīng)后臺(tái)來(lái)電呢套像?
其實(shí)蘋果官方CoreTelephony.framework中已經(jīng)提供了相應(yīng)監(jiān)聽(tīng)來(lái)電方法。
來(lái)看看系統(tǒng)提供的方法:
CTCallCenter *center = [[CTCallCenter alloc] init];
center.callEventHandler = ^(CTCall *call) {
if ([call.callState isEqualToString:CTCallStateIncoming]) {
//來(lái)電
}else if ([call.callState isEqualToString:CTCallStateConnected]) {
//接通
}else if ([call.callState isEqualToString:CTCallStateDisconnected]) {
//掛斷
}else if ([call.callState isEqualToString:CTCallStateDialing]) {
//正在通話
}else {
//其他
}
};
如果你照搬上面的代碼终息,會(huì)發(fā)現(xiàn)不能監(jiān)聽(tīng)來(lái)電夺巩,因?yàn)樵贏RC模式下,center創(chuàng)建后周崭,就要被釋放了柳譬。所以,如果要監(jiān)聽(tīng)來(lái)電续镇,必須把center對(duì)象定義為全局或者被某個(gè)對(duì)象引用美澳,不要被釋放掉,或者再不需要監(jiān)聽(tīng)來(lái)電后磨取,再釋放掉人柿。
好,即使你采用了我上面的建議忙厌,最后還是發(fā)現(xiàn)有些不太完美凫岖。
上面的方法的確能夠監(jiān)聽(tīng)來(lái)電了,但是只能在APP運(yùn)行時(shí)逢净,才能夠正常監(jiān)聽(tīng)哥放;如果APP進(jìn)入后臺(tái),就再也監(jiān)聽(tīng)不到了爹土。尷尬I瘛!胀茵!
重點(diǎn)來(lái)了社露,我怎么才能讓后臺(tái)監(jiān)聽(tīng)來(lái)電呢?
我們先把問(wèn)題分解琼娘,上面的需求可以分解為兩個(gè)峭弟。一個(gè)是后臺(tái)運(yùn)行附鸽;另一個(gè)是監(jiān)聽(tīng)來(lái)電。
一瞒瘸、怎么才能后臺(tái)運(yùn)行呢坷备?
蘋果官方給出以下可以申請(qǐng)后臺(tái)運(yùn)行:
1.Audio and AirPlay(音頻播放)
2.Location updates(位置更新)
3.Voice over IP(voip)
4.Newsstand downloads
5.External accessory communication
6.Uses Bluetooth LE accessories
7.Acts as a Bluetooth LE accessory
8.Background fetch
9.Remote notifications
以上9種,都可以申請(qǐng)后臺(tái)運(yùn)行情臭。很好省撑,因?yàn)槲覀兊乃{(lán)牙4.0開發(fā),也可以申請(qǐng)后臺(tái)運(yùn)行俯在。
那么怎么才能做到我們藍(lán)牙4.0相關(guān)的APP能夠后臺(tái)運(yùn)行呢竟秫?我給出的做法,是使用定時(shí)器朝巫。
1鸿摇、定義一個(gè)屬性變量定時(shí)器。定義成屬性變量劈猿,方便我們?cè)诓皇褂脮r(shí)拙吉,進(jìn)行銷毀。比如APP進(jìn)入前臺(tái)時(shí)揪荣。
@property (nonatomic, strong) NSTimer *phoneTimer;
2筷黔、定時(shí)器
if (self.phoneTimer == nil) {
self.phoneTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(commTimer:) userInfo:nil repeats:YES];
}
3、發(fā)送藍(lán)牙數(shù)據(jù)仗颈。(如果實(shí)際當(dāng)中佛舱,我們并不需要后臺(tái)發(fā)送數(shù)據(jù)時(shí),可以發(fā)送一些無(wú)意義的數(shù)據(jù)挨决,只是達(dá)到后臺(tái)運(yùn)行的目的)
- (void)commTimer:(NSTimer *)timer {
//發(fā)送藍(lán)牙數(shù)據(jù)
}
好啦请祖,上面三步就可以完成藍(lán)牙4.0后臺(tái)運(yùn)行。當(dāng)然不要忘記了在plist文件中申請(qǐng)相應(yīng)的權(quán)限脖祈。如下圖:
二肆捕、怎樣在后臺(tái)時(shí),監(jiān)聽(tīng)來(lái)電呢盖高?
如果你在定時(shí)執(zhí)行的commTimer
方法中慎陵,執(zhí)行callEventHandler
監(jiān)聽(tīng)方法,會(huì)發(fā)現(xiàn)依然監(jiān)聽(tīng)不到來(lái)電喻奥。
仔細(xì)看蘋果提供的CTCallCenter
類席纽,會(huì)發(fā)現(xiàn)還有一個(gè)屬性變量currentCalls
。
/*
* CTCallCenter.h
* CFTelephony
*
* Copyright 2010 Apple, Inc. All rights reserved.
*
*/
#import <Foundation/Foundation.h>
#import <CoreTelephony/CoreTelephonyDefines.h>
@class CTCall;
NS_ASSUME_NONNULL_BEGIN
CORETELEPHONY_CLASS_AVAILABLE(4_0)
@interface CTCallCenter : NSObject
/*
* currentCalls
*
* Discussion:
* An array containing CTCall objects for all calls that are currently
* in progress. If no calls are active, this will be nil.
*
*/
@property(readonly, retain, nullable) NSSet<CTCall*> *currentCalls __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_NA, __MAC_NA, __IPHONE_4_0, __IPHONE_10_0, "Replaced by <CallKit/CXCallObserver.h>");
/*
* callEventHandler
*
* Discussion:
* A block that will be dispatched on the default priority global dispatch
* queue when a new call event occurs. Set this property to a block
* that is defined in your application to handle call events.
*/
@property(nonatomic, copy, nullable) void (^callEventHandler)(CTCall*) __OSX_AVAILABLE_BUT_DEPRECATED_MSG(__MAC_NA, __MAC_NA, __IPHONE_4_0, __IPHONE_10_0, "Replaced by <CallKit/CXCallObserver.h>");
@end
NS_ASSUME_NONNULL_END
對(duì)撞蚕,我們就從這個(gè)變量入手润梯。來(lái)重寫commTimer
方法。代碼示意如下:
/**
后臺(tái)發(fā)送藍(lán)牙數(shù)據(jù)、監(jiān)聽(tīng)來(lái)電
*/
- (void)commTimer:(NSTimer *)timer {
//發(fā)送藍(lán)牙數(shù)據(jù)
if ([[BTManager shareManager] isConnect]) {
[[BTManager shareManager] sendBackgroudData];
//監(jiān)聽(tīng)來(lái)電
CTCallCenter *center = [[CTCallCenter alloc] init];
if (center.currentCalls) {
CTCall *call = [center.currentCalls anyObject];
if ([call.callState isEqual:CTCallStateIncoming]) {
isPhone = YES;
[[BTManager shareManager] phoneCallIn];
}else if ([call.callState isEqual:CTCallStateDisconnected]) {
if (isPhone) {
isPhone = NO;
[[BTManager shareManager] phoneCallEnd];
}
}else {
}
}
}
}
BTManager
是我設(shè)計(jì)的一個(gè)藍(lán)牙管理類仆救,用來(lái)管理收發(fā)藍(lán)牙數(shù)據(jù)的抒和。
isConnect
方法是判斷當(dāng)前是否有藍(lán)牙連接,當(dāng)然你也可以設(shè)計(jì)中彤蔽,當(dāng)藍(lán)牙斷開連接時(shí),就停止定時(shí)器庙洼。
sendBackgroudData
發(fā)送是數(shù)據(jù)顿痪,保持藍(lán)牙后臺(tái)長(zhǎng)連接。
以上就是我在iOS藍(lán)牙4.0后臺(tái)監(jiān)聽(tīng)來(lái)電的解決方案油够。希望對(duì)藍(lán)牙4.0開發(fā)的伙伴們有所幫助蚁袭,有幫助的點(diǎn)個(gè)贊吧!哈哈JА揩悄!