以编程方式断开或连接一个iPhone电话[英] Disconnect or connect an iPhone call programmatically

本文是小编为大家收集整理的关于以编程方式断开或连接一个iPhone电话的处理方法,想解了以编程方式断开或连接一个iPhone电话的问题怎么解决?以编程方式断开或连接一个iPhone电话问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

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

这是我的代码:

@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'".

我该如何解决这个问题?有没有办法在挂钩方法时使用私有实例变量?是否有返回来电 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 为止.我不太了解徽标/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;
}

本文地址:https://www.itbaoku.cn/post/924442.html