這裡的實現原理是獲取到來電系統通知,然後根據本地通話的電話號碼,把對應電話的聯系人.
情況一 來電號碼未在通訊錄聯系人中, 這時候要先在通訊錄添加一個臨時的聯系人(就是新建一個聯系人,並保存對應的RecordID)
情況二 已在通訊錄的聯系人
然後 把對應本次通話的電話標簽修改成歸屬地字符
好了 ,先看看怎麼獲取系統電話通知
需要的類
//創建電話對象
代碼一:
#import
@import CoreTelephony;
// private API
typedef NS_ENUM(short, CTCallStatus) {
kCTCallStatusConnected = 1, //已接通
kCTCallStatusCallOut = 3, //撥出去
kCTCallStatusCallIn = 4, //打進來
kCTCallStatusHungUp = 5 //掛斷
};
@interface WCCall : NSObject
@property (nonatomic,assign) CTCallStatus callStatus;
@property (nonatomic,copy) NSString *phoneNumber;
@property (nonatomic,retain) CTCall *internalCall;
@end
#import WCCall.h
@implementation WCCall
@end
//監聽電話通知
代碼三:
#import
#import WCCall.h
@interface WCCallCenter : NSObject
// 監聽來電事件
@property (nonatomic,strong) void (^callEventHandler)(WCCall *call);
// 掛斷電話
- (void)disconnectCall:(WCCall *)call;
@end
代碼四:
#import WCCallCenter.h
#import WCUtil.h
// encrypted string's
#define ENCSTR_kCTCallStatusChangeNotification [@n0AHD2SfoSA0LKE1p0AbLJ5aMH5iqTyznJAuqTyiot== wcDecryptString]
#define ENCSTR_kCTCall [@n0AHD2SfoN== wcDecryptString]
#define ENCSTR_kCTCallStatus [@n0AHD2SfoSA0LKE1pj== wcDecryptString]
#define ENCSTR_CTTelephonyCenterGetDefault [@D1EHMJkypTuioayQMJ50MKWUMKERMJMuqJk0 wcDecryptString]
#define ENCSTR_CTTelephonyCenterAddObserver [@D1EHMJkypTuioayQMJ50MKWOMTECLaAypaMypt== wcDecryptString]
#define ENCSTR_CTTelephonyCenterRemoveObserver [@D1EHMJkypTuioayQMJ50MKWFMJ1iqzICLaAypaMypt== wcDecryptString]
#define ENCSTR_CTCallCopyAddress [@D1EQLJkfD29jrHSxMUWyp3Z= wcDecryptString]
#define ENCSTR_CTCallDisconnect [@D1EQLJkfETymL29hozIwqN== wcDecryptString]
//這裡需要對字符串 NSString 進行拓展方法
//#import
/**
- (NSString *)wcRot13
{
const char *source = [selfcStringUsingEncoding:NSASCIIStringEncoding];
char *dest = (char *)malloc((self.length +1) * sizeof(char));
if (!dest) {
return nil;
}
NSUInteger i = 0;
for ( ; i < self.length; i++) {
char c = source[i];
if (c >= 'A' && c <='Z') {
c = (c - 'A' + 13) % 26 + 'A';
}
else if (c >='a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
}
dest[i] = c;
}
dest[i] = '';
NSString *result = [[NSStringalloc] initWithCString:destencoding:NSASCIIStringEncoding];
free(dest);
return result;
}
- (NSString *)wcDecryptString
{
NSString *rot13 = [selfwcRot13];
NSData *data;
if ([NSDatainstancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
data = [[NSDataalloc] initWithBase64EncodedString:rot13options:0]; // iOS 7+
} else {
data = [[NSData alloc] initWithBase64Encoding:rot13]; // pre iOS7
}
return [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];
}
**/
// private API
//extern NSString *CTCallCopyAddress(void*, CTCall *);
typedef NSString *(*PF_CTCallCopyAddress)(void*,CTCall *);
//extern void CTCallDisconnect(CTCall *);
typedef void (*PF_CTCallDisconnect)(CTCall *);
//extern CFNotificationCenterRef CTTelephonyCenterGetDefault();
typedef CFNotificationCenterRef (*PF_CTTelephonyCenterGetDefault)();
typedef void (*PF_CTTelephonyCenterAddObserver)(CFNotificationCenterRef center,
constvoid *observer,
CFNotificationCallback callBack,
CFStringRef name,
constvoid *object,
CFNotificationSuspensionBehavior suspensionBehavior);
typedef void (*PF_CTTelephonyCenterRemoveObserver)(CFNotificationCenterRef center,
constvoid *observer,
CFStringRef name,
constvoid *object);
@interface WCCallCenter ()
- (void)handleCall:(CTCall *)call withStatus:(CTCallStatus)status;
@end
@implementation WCCallCenter
- (id)init
{
self = [superinit];
if (self) {
[selfregisterCallHandler];
}
return self;
}
- (void)dealloc
{
[selfderegisterCallHandler];
}
- (void)registerCallHandler
{
staticPF_CTTelephonyCenterAddObserver AddObserver;
staticPF_CTTelephonyCenterGetDefault GetCenter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
AddObserver = [WCDLloadSymbol:ENCSTR_CTTelephonyCenterAddObserver];
GetCenter = [WCDLloadSymbol:ENCSTR_CTTelephonyCenterGetDefault];
});
AddObserver(GetCenter(),
(__bridge void *)self,
&callHandler,
(__bridgeCFStringRef)(ENCSTR_kCTCallStatusChangeNotification),
NULL,
CFNotificationSuspensionBehaviorHold);
}
- (void)deregisterCallHandler
{
staticPF_CTTelephonyCenterRemoveObserver RemoveObserver;
staticPF_CTTelephonyCenterGetDefault GetCenter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
RemoveObserver = [WCDLloadSymbol:ENCSTR_CTTelephonyCenterRemoveObserver];
GetCenter = [WCDLloadSymbol:ENCSTR_CTTelephonyCenterGetDefault];
});
RemoveObserver(GetCenter(),
(__bridge void *)self,
(__bridgeCFStringRef)(ENCSTR_kCTCallStatusChangeNotification),
NULL);
}
- (void)handleCall:(CTCall *)call withStatus:(CTCallStatus)status
{
staticPF_CTCallCopyAddress CopyAddress;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CopyAddress = [WCDL loadSymbol:ENCSTR_CTCallCopyAddress];
});
if (!self.callEventHandler || !call) {
return;
}
WCCall *wcCall = [[WCCallalloc] init];
wcCall.phoneNumber = CopyAddress(NULL, call);
wcCall.phoneNumber = wcCall.phoneNumber;
wcCall.callStatus = status;
wcCall.internalCall = call;
self.callEventHandler(wcCall);
}
static void callHandler(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
if (!observer) {
return;
}
NSDictionary *info = (__bridgeNSDictionary *)(userInfo);
CTCall *call = (CTCall *)info[ENCSTR_kCTCall];
CTCallStatus status = (CTCallStatus)[info[ENCSTR_kCTCallStatus]shortValue];
if ([[calldescription] rangeOfString:@status = 196608].location==NSNotFound) {
//這裡之後就是你對歸屬地信息的操作了
WCCallCenter *wcCenter = (__bridgeWCCallCenter*)observer;
[wcCenter handleCall:call withStatus:status];
}
}
- (void)disconnectCall:(WCCall *)call
{
staticPF_CTCallDisconnect Disconnect;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Disconnect = [WCDL loadSymbol:ENCSTR_CTCallDisconnect];
});
CTCall *ctCall = call.internalCall;
if (!ctCall) {
return;
}
Disconnect(ctCall);
}
@end
//處理本地通話的一些操作
#import
@interface WCCallInspector : NSObject
+ (instancetype)sharedInspector;
- (void)startInspect;//啟動 O(∩_∩)O~~
@end
#import WCCallInspector.h
#import WCCallCenter.h
#import
@interface WCCallInspector ()
@property (nonatomic,strong) WCCallCenter *callCenter;
@end
@implementation WCCallInspector
+ (instancetype)sharedInspector
{
static WCCallInspector *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[WCCallInspector alloc] init];
});
return instance;
}
- (id)init
{
self = [superinit];
if (self) {
}
return self;
}
#pragma mark - Call Inspection
- (void)startInspect
{
if (self.callCenter) {
return;
}
self.callCenter = [[WCCallCenteralloc] init];
__weak WCCallInspector *weakSelf =self;
self.callCenter.callEventHandler = ^(WCCall *call) {
[weakSelf handleCallEvent:call];
};
}
#pragma mark 呼出,呼入,接通,掛斷
- (void)handleCallEvent:(WCCall *)call{
//這裡 想怎麼操作 根據自己情況而定啊......
//可以打印call的屬性看看結果
// kCTCallStatusConnected = 1, //已接通
// kCTCallStatusCallOut = 3, //撥出去
// kCTCallStatusCallIn = 4, //打進來
// kCTCallStatusHungUp = 5 //掛斷
}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/**
* Your Code
**/
[[WCCallInspectorsharedInspector] startInspect];
return YES;
}
程序啟動的情況下 來電/去電/接通/掛斷 都可以獲到了, 文章到此結束了, 敬請期待 對聯系人添加歸屬地, 修改聯系人操作博客.....