您的位置:首页 > 移动开发 > IOS开发

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

2015-06-26 13:33 357 查看
转自:http://www.tuicool.com/articles/niQvMr

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

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

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

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

原文地址 /article/2382126.html

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

需要的类



//创建电话对象

代码一:

#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 = [ self cStringUsingEncoding : 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 = [[ NSString alloc ] initWithCString :dest encoding :NSASCIIStringEncoding ];

free (dest);

return result;

}

- ( NSString *)wcDecryptString

{

NSString *rot13 = [ self wcRot13 ];

NSData *data;

if ([ NSData instancesRespondToSelector : @selector(initWithBase64EncodedString:options:)]) {

data = [[ NSData alloc ] initWithBase64EncodedString :rot13 options : 0 ]; // iOS 7+

} else {

data = [[ NSData alloc ] initWithBase64Encoding :rot13]; // pre iOS7

}

return [[ NSString alloc ] initWithData :data encoding : 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)( CFNotificationCenterRefcenter,

const void *observer,

CFNotificationCallback callBack,

CFStringRef name,

const void *object,

CFNotificationSuspensionBehavior suspensionBehavior);

typedef void (*PF_CTTelephonyCenterRemoveObserver)( CFNotificationCenterRefcenter,

const void *observer,

CFStringRef name,

const void *object);

@interface WCCallCenter ()

- ( void )handleCall:( CTCall *)call withStatus:( CTCallStatus )status;

@end

@implementation WCCallCenter

- ( id )init

{

self = [ super init ];

if ( self ) {

[ self registerCallHandler ];

}

return self ;

}

- ( void )dealloc

{

[ self deregisterCallHandler ];

}

- ( void )registerCallHandler

{

static PF_CTTelephonyCenterAddObserver AddObserver;

static PF_CTTelephonyCenterGetDefault GetCenter;

static dispatch_once_t onceToken;

dispatch_once (&onceToken, ^{

AddObserver = [ WCDL loadSymbol : ENCSTR_CTTelephonyCenterAddObserver ];

GetCenter = [ WCDL loadSymbol : ENCSTR_CTTelephonyCenterGetDefault ];

});

AddObserver(GetCenter(),

( __bridge void *) self ,

& callHandler ,

( __bridge CFStringRef )( ENCSTR_kCTCallStatusChangeNotification ),

NULL ,

CFNotificationSuspensionBehaviorHold );

}

- ( void )deregisterCallHandler

{

static PF_CTTelephonyCenterRemoveObserver RemoveObserver;

static PF_CTTelephonyCenterGetDefault GetCenter;

static dispatch_once_t onceToken;

dispatch_once (&onceToken, ^{

RemoveObserver = [ WCDL loadSymbol :ENCSTR_CTTelephonyCenterRemoveObserver ];

GetCenter = [ WCDL loadSymbol : ENCSTR_CTTelephonyCenterGetDefault ];

});

RemoveObserver(GetCenter(),

( __bridge void *) self ,

( __bridge CFStringRef )( ENCSTR_kCTCallStatusChangeNotification ),

NULL );

}

- ( void )handleCall:( CTCall *)call withStatus:( CTCallStatus )status

{

static PF_CTCallCopyAddress CopyAddress;

static dispatch_once_t onceToken;

dispatch_once (&onceToken, ^{

CopyAddress = [ WCDL loadSymbol : ENCSTR_CTCallCopyAddress ];

});

if (! self . callEventHandler || !call) {

return ;

}

WCCall *wcCall = [[ WCCall alloc ] 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 = ( __bridge NSDictionary *)(userInfo);

CTCall *call = ( CTCall *)info[ ENCSTR_kCTCall ];

CTCallStatus status = ( CTCallStatus )[info[ ENCSTR_kCTCallStatus ] shortValue ];

if ([[call description ] rangeOfString : @"status = 196608" ]. location == NSNotFound ) {

//这里之后就是你对归属地信息的操作了

WCCallCenter *wcCenter = ( __bridge WCCallCenter *)observer;

[wcCenter handleCall :call withStatus :status];

}

}

- ( void )disconnectCall:( WCCall *)call

{

static PF_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 = [ super init ];

if ( self ) {

}

return self ;

}

#pragma mark - Call Inspection

- ( void )startInspect

{

if ( self . callCenter ) {

return ;

}

self . callCenter = [[ WCCallCenter alloc ] 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

**/

[[ WCCallInspector sharedInspector ] startInspect ];

return YES ;

}

//引用这个类库

#import

<AudioToolbox/AudioToolbox.h>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: