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>
这里的实现原理是获取到来电系统通知,然后根据本地通话的电话号码,把对应电话的联系人.
情况一 来电号码未在通讯录联系人中, 这时候要先在通讯录添加一个临时的联系人(就是新建一个联系人,并保存对应的 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>
相关文章推荐
- iOS 适用于大写英文的全角转半角
- 苹果开发者账号注册&真机调试
- iOS 9系统安装空间需求下降至1.8GB
- ios九宫格
- iOS7后导航栏的问题
- iOS_ScrollView的自动布局
- iOS-键盘弹出遮挡问题
- iOS开发-文件管理
- iOS设计模式之单例模式
- iOS蓝牙篇 GameKit,在iOS7.0之前的设备上的主流开发(必须是同一个应用程序),现已过时,仅用于学习
- iOS关于横屏window坐标的问题
- iOS 页面间几种传值方式(属性,代理,block,单例,通知)
- 调用ios系统生成二维码
- 好玩的ios游戏
- iOS8 open Settings
- iOS 9适配系列教程:后台定位
- iOS 8的scrollView上的试图都不显示(scrollView直接加在带navigation的self.view上
- 网易新闻iOS版使用的18个开源组件
- ios 开发记录 点点滴滴
- 【iOS】国际化(对一些有用资源的汇总)