首页 > 代码库 > IOS获取来电去电系统通知达到来电归属地效果(一)

IOS获取来电去电系统通知达到来电归属地效果(一)

这里的实现原理是获取到来电系统通知,然后根据本地通话的电话号码,把对应电话的联系人.

情况一   来电号码未在通讯录联系人中, 这时候要先在通讯录添加一个临时的联系人(就是新建一个联系人,并保存对应的RecordID)

情况二  已在通讯录的联系人

然后 把对应本次通话的电话标签修改成归属地字符



原文地址    http://blog.csdn.net/leewolf130/article/details/38921921


好了 ,先看看怎么获取系统电话通知

需要的类



//创建电话对象

代码一: 

#import <Foundation/Foundation.h>

@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 <Foundation/Foundation.h>

#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 <dlfcn.h> 引用 这个框架


/**

- (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] = ‘\0‘;

    

    NSString *result = [[NSStringalloc]initWithCString:destencoding:NSASCIIStringEncoding];

    free(dest);

    

    return result;

}

- (NSString *)wcDecryptString

{

    NSString *rot13 = [selfwcRot13];

    NSData *data;

    if ([NSDatainstancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {

        data = http://www.mamicode.com/[[NSDataalloc]initWithBase64EncodedString:rot13options:0]; // iOS 7+

    } else {

        data = http://www.mamicode.com/[[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 <Foundation/Foundation.h>

@interface WCCallInspector : NSObject


+ (instancetype)sharedInspector;

- (void)startInspect;//启动 O(_)O~~


@end


代码六:

#import "WCCallInspector.h"

#import "WCCallCenter.h"

#import <AudioToolbox/AudioToolbox.h>


@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 //挂断

}

//startInspect//这个方法需要在程序启动时候注册

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    /**

     * Your Code

     **/

    [[WCCallInspectorsharedInspector]startInspect];

    return YES;

}


//引用这个类库
#import <AudioToolbox/AudioToolbox.h>

转载请标明 原文地址    http://blog.csdn.net/leewolf130/article/details/38921921

程序启动的情况下    来电/去电/接通/挂断    都可以获到了,  文章到此结束了, 敬请期待  对联系人添加归属地, 修改联系人操作博客.....



IOS获取来电去电系统通知达到来电归属地效果(一)