以编程方式断开或连接iPhone电话

我正在为iOS进行个人调整。 我想在手机显示任何内容之前断开/连接电话。 我钩入类SBUIFullscreenAlertAdapterinitWithAlertController:方法。 一切都好,当我只显示一个消息,显示传入的电话号码和它的名字,但是当我尝试接听电话或断开它编程,它会崩溃,并进入安全模式。

这是我的代码:

 @interface SBUIFullscreenAlertAdapter - (id)initWithAlertController:(id)arg1; @end @interface MPIncomingPhoneCallController { struct __CTCall *_incomingCall; } - (id) incomingCallNumber; - (void)stopRingingOrVibrating; - (void)answerCall:(struct __CTCall *)arg1; @end %hook SBUIFullscreenAlertAdapter - (id)initWithAlertController:(id)arg1 { MPIncomingPhoneCallController *phoneCall = (MPIncomingPhoneCallController*)arg1; [phoneCall stopRingingOrVibrating]; if([phoneCall.incomingCallNumber isEqualToString:@"+98.........."]) { [phoneCall answerCall:_incomingCall]; } %orig; return self; } %end 

错误是它说:“使用未声明的标识符_incomingCall'”。

我该如何解决这个问题? 有一种方法来挂钩一个方法时使用私有实例variables? 有没有一个函数返回来电的CTCallRef* ? 有没有其他的方法来完成这个?

很明显,我为越狱的iOS设备编码,所以使用私有框架没有问题。

有更好的地方做 – MPTelephonyManager -(void)displayAlertForCall:(id)call 。 这个方法位于IncomingCall.servicebundle二进制文件中,而不是在SpringBoard中。 当有一个来电时,这个二进制文件在运行时被加载到SpringBoard中。 在这之前IncomingCall.servicebundle没有加载,因此你不能挂钩它的方法。

挂接IncomingCall.servicebundle

为了钩住这个方法,首先阅读这个如何挂钩MPIncomingPhoneCallController的方法? SBPluginManager正在加载* .servicebundle二进制文件在运行时。 你需要挂钩-(Class)loadPluginBundle:(id)bundle方法。 它会看起来像这样:

 void displayAlertForCall_hooked(id self, SEL _cmd, id arg1); void(*displayAlertForCall_orig)(id, SEL, id) = NULL; %hook SBPluginManager -(Class)loadPluginBundle:(NSBundle*)bundle { Class ret = %orig; if ([[bundle bundleIdentifier] isEqualToString:@"com.apple.mobilephone.incomingcall"] && [bundle isLoaded]) { MSHookMessageEx(objc_getClass("MPTelephonyManager"), @selector(displayAlertForCall:), (IMP)displayAlertForCall_hooked, (IMP*)&displayAlertForCall_orig); } return ret; } %end 

正如你所看到的,挂钩被推迟到IncomingCall.servicebundle被加载。 我不知道标识/理论,但我认为它不能这样做。 这就是为什么我使用CydiaSubstrate(MobileSubstrate)API。

挂钩MPTelephonyManager

 #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) typedef void* CTCallRef; void CTCallDisconnect(CTCallRef); void CTCallAnswer(CTCallRef); void displayAlertForCall_hooked(id self, SEL _cmd, id arg1) { CTCallRef call = NULL; if (SYSTEM_VERSION_LESS_THAN(@"7.0")) { //On iOS 6 and below arg1 has CTCallRef type call = arg1; } else { //On iOS 7 arg1 has TUTelephonyCall* type call = [arg1 call]; } NSString *callNumber = (NSString*)CFBridgingRelease(CTCallCopyAddress(NULL, call)); if ([callNumber isEqualToString:@"+98.........."]) { CTCallAnswer(call); //CTCallDisconnect(call); } %orig; } 

对于iOS 8. *:

Theos / Logos的挂钩似乎很容易。

示例Tweak.xm文件(您需要8.1版的TelephonyUtilities私有框架头文件):

 #import "TelephonyUtilities/TUTelephonyCall.h" %hook MPTelephonyManager -(void)displayAlertForCall:(TUTelephonyCall*)phoneCall { // for iOS 9: displayAlertForCallIfNecessary NSLog(@"hooked displayAlertForCall method"); if ([[NSBundle mainBundle].bundleIdentifier isEqualToString:@"com.apple.springboard"]) { // (don't know if required) [phoneCall answer]; // or [phoneCall disconnect]; } %orig; } %end %ctor { if ([[NSBundle bundleWithPath:@"/System/Library/SpringBoardPlugins/IncomingCall.servicebundle"] load]) { NSLog(@"IncomingCall.servicebundle loaded succesfully!"); } else { NSLog(@"IncomingCall.servicebundle did not load succesfully."); } } 

感谢Phillip Tennen( https://github.com/codyd51/CallConnect