以编程方式断开或连接iPhone呼叫

时间:2014-03-20 11:44:40

标签: ios iphone objective-c jailbreak

我正在为iOS进行个人调整。我想在电话显示任何内容之前断开/连接电话。我正在使用类initWithAlertController:的{​​{1}}方法。当我只显示一条显示来电号码及其姓名的消息时,一切都还可以,但是当我尝试接听电话或以编程方式断开电话时,它会崩溃并进入安全模式。

这是我的代码:

SBUIFullscreenAlertAdapter

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

我该如何解决这个问题?有没有办法在挂钩方法时使用私有实例变量?是否有一个函数可以返回@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 来电?还有其他方法可以实现这个目标吗?

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

2 个答案:

答案 0 :(得分:4)

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


挂钩IncomingCall.servicebundle

为了挂钩该方法,首先,阅读此How to hook methods of 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加载为止。我不太了解徽标/ theos,但我认为它不能那样做。这就是我使用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;
}

答案 1 :(得分:1)

适用于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