0

I'm trying to write an app for an iPhone using Apple Private APIs. This is for personal developer purpose only. It won't be submitted to the app store so I don't have to worry about rejection.

I've followed the instructions in this video, but I'm not quite sure how to fix these compiling errors:

enter image description here

Here's the Youtube link: https://www.youtube.com/watch?v=OLX7b_KZIvg

These are the steps to produce these errors incase you don't want to watch the Youtube video:

  1. Download the Private Framework Headers from this url: https://github.com/kennytm/iphone-private-frameworks/tree/master
  2. Unzip the downloaded file
  3. Copy the desired class into the Xcode PrivateFrameworks path, my path is: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/PrivateFrameworks (I used the TelephonyUtilities.framework)
  4. Create a new Project in Xcode (I'm using version 7.2)
  5. Go to Project/Build Settings and set the "Framework Search Paths" value to /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/PrivateFrameworks (You might have a slightly different path)
  6. Go Project/General and add the library TelephonyUtilities.framework to "Linked Frameworks and Libraries" section

Note: 1. At this point, you should be able to build without errors 2. Should also see the private framework in the project folder in the left panel.

  1. Now, if you add a header to the ViewController.h in the project, and build, you get the errors shown image above.

Here's my ViewController.h file:

#import <UIKit/UIKit.h>
#include <TelephonyUtilities/TUCallCenter.h>  // <<<<< This line causes the compilation errors

@interface ViewController : UIViewController


@end

The reason for me to use the private API is I want my app to accept an incoming call and the public API doesn't allow it.

Any help or pointer to resolve this would be appreciated.

Thanks

Will
  • 1,718
  • 3
  • 15
  • 23

2 Answers2

0

In case anyone is wondering, the fix for what I needed was quite simple. Luckily, I didn't need all the functions available in the TUCallCenter class. I just needed a few and I could get away with commenting out the unnecessary lines.

Here are the changes to the TUCallCenter.h header file:

/* Generated by RuntimeBrowser
   Image: /System/Library/PrivateFrameworks/TelephonyUtilities.framework/TelephonyUtilities
 */

#include "TUCallModelState.h"  // <<< Had to add this because TUCallModelState is used below

@interface TUCallCenter : NSObject {
    TUCallModelState *_callModelState;
}

//@property (nonatomic, readonly, retain) TUCall *activeVideoCall;
//@property (nonatomic, readonly) BOOL anyCallIsEndpointOnCurrentDevice;
//@property (nonatomic, readonly) BOOL anyCallIsHostedOnCurrentDevice;
//@property (nonatomic, readonly) unsigned int callCountOnDefaultPairedDevice;
//@property (nonatomic, readonly, copy) NSArray *callGroupsOnDefaultPairedDevice;
@property (nonatomic, retain) TUCallModelState *callModelState;
//@property (nonatomic, readonly, copy) NSArray *callsHostedElsewhere;
//@property (nonatomic, readonly, copy) NSArray *callsHostedOrAnEndpointElsewhere;
//@property (nonatomic, readonly, copy) NSArray *callsOnDefaultPairedDevice;
//@property (nonatomic, readonly, copy) NSArray *callsWithAnEndpointElsewhere;
//@property (nonatomic, readonly, copy) NSArray *conferenceParticipantCalls;
//@property (nonatomic, readonly) unsigned int currentAudioAndVideoCallCount;
//@property (nonatomic, readonly, copy) NSArray *currentAudioAndVideoCalls;
//@property (nonatomic, readonly) unsigned int currentCallCount;
//@property (nonatomic, readonly, retain) NSArray *currentCallGroups;
//@property (nonatomic, readonly, copy) NSArray *currentCalls;
//@property (nonatomic, readonly, retain) TUCall *currentVideoCall;
//@property (nonatomic, readonly) unsigned int currentVideoCallCount;
//@property (nonatomic, readonly, copy) NSArray *currentVideoCalls;
//@property (nonatomic, readonly, copy) NSArray *displayedCalls;
//@property (nonatomic, readonly, retain) TUCall *incomingCall;
//@property (nonatomic, readonly, copy) NSArray *incomingCalls;
//@property (nonatomic, readonly, retain) TUCall *incomingVideoCall;
//
//+ (id)_sharedInstanceWithDaemonDelegate:(id)arg1;
//+ (BOOL)emergencyCallBackModeIsActive;
+ (BOOL)isInCallServiceProcess;
//+ (void*)sharedAddressBook;
+ (id)sharedInstance;
//
//- (void).cxx_destruct;
//- (id)_allCalls;
//- (id)_callGroupsFromCalls:(id)arg1;
//- (void)_callStatusChangedInternal:(id)arg1;
//- (id)_dial:(id)arg1 callID:(int)arg2 service:(int)arg3 sourceIdentifier:(id)arg4 dialType:(int)arg5 uniqueProxyIdentifier:(id)arg6;
//- (id)_dialWithRequest:(id)arg1 completion:(id /* block */)arg2;
//- (void)_handleCallControlFailure:(id)arg1;
//- (id)activeVideoCall;
//- (BOOL)allCallsAreOfService:(int)arg1;
//- (BOOL)allCallsPassTest:(id /* block */)arg1;
//- (int)ambiguityState;
- (void)answerCall:(id)arg1;
//- (void)answerCall:(id)arg1 withSourceIdentifier:(id)arg2;
//- (void)answerCall:(id)arg1 withSourceIdentifier:(id)arg2 wantsHoldMusic:(BOOL)arg3;
//- (void)answerCallWithHoldMusic:(id)arg1;
//- (BOOL)anyCallIsEndpointOnCurrentDevice;
//- (BOOL)anyCallIsHostedOnCurrentDevice;
//- (BOOL)anyCallPassesTest:(id /* block */)arg1;
//- (id)audioAndVideoCallsWithStatus:(int)arg1;
//- (id)audioOrVideoCallWithStatus:(int)arg1;
//- (unsigned int)callCountOnDefaultPairedDevice;
//- (id)callGroupsOnDefaultPairedDevice;
//- (id)callModelState;
//- (id)callPassingTest:(id /* block */)arg1;
//- (id)callPassingTest:(id /* block */)arg1 sortedUsingComparator:(id /* block */)arg2;
//- (id)callPassingTest:(id /* block */)arg1 withOptions:(unsigned int)arg2;
//- (id)callWithCallUUID:(id)arg1;
//- (id)callWithStatus:(int)arg1;
//- (id)callWithUniqueProxyIdentifier:(id)arg1;
//- (id)callsHostedElsewhere;
//- (id)callsHostedOrAnEndpointElsewhere;
//- (id)callsOnDefaultPairedDevice;
//- (id)callsPassingTest:(id /* block */)arg1;
//- (id)callsPassingTest:(id /* block */)arg1 returningNilForEmpty:(BOOL)arg2;
//- (id)callsWithAnEndpointElsewhere;
//- (id)callsWithStatus:(int)arg1;
//- (BOOL)canInitiateCallForService:(int)arg1;
//- (BOOL)canInitiateCalls;
//- (BOOL)canInitiateVoicemailCall;
//- (BOOL)canMergeCalls;
//- (BOOL)canUseThumperOverRelayForIncomingAndOutgoingCalls;
//- (id)conferenceCall;
//- (id)conferenceParticipantCalls;
//- (unsigned int)countOfCallsPassingTest:(id /* block */)arg1;
//- (unsigned int)currentAudioAndVideoCallCount;
//- (id)currentAudioAndVideoCalls;
//- (unsigned int)currentCallCount;
//- (id)currentCallGroups;
//- (id)currentCalls;
//- (id)currentVideoCall;
//- (unsigned int)currentVideoCallCount;
//- (id)currentVideoCalls;
//- (void)dealloc;
//- (id)dial:(id)arg1 callID:(int)arg2 service:(int)arg3;
//- (id)dial:(id)arg1 callID:(int)arg2 service:(int)arg3 sourceIdentifier:(id)arg4 uniqueProxyIdentifier:(id)arg5;
//- (id)dial:(id)arg1 service:(int)arg2;
//- (id)dialEmergency:(id)arg1;
//- (id)dialEmergency:(id)arg1 sourceIdentifier:(id)arg2;
//- (id)dialVoicemail;
//- (id)dialVoicemailWithSourceIdentifier:(id)arg1;
//- (id)dialWithRequest:(id)arg1;
//- (void)dialWithRequest:(id)arg1 completion:(id /* block */)arg2;
//- (void)disconnectAllCalls;
//- (void)disconnectCall:(id)arg1;
//- (void)disconnectCall:(id)arg1 withReason:(int)arg2;
//- (void)disconnectCurrentCallAndActivateHeld;
//- (void)disconnectNonRelayingCalls;
//- (void)disconnectRelayingCalls;
//- (id)displayedCall;
//- (id)displayedCallFromCalls:(id)arg1;
//- (id)displayedCalls;
//- (void)endActiveAndAnswerCall:(id)arg1;
//- (void)endActiveOrHeldAndAnswerCall:(id)arg1;
//- (void)endEmergencyCallBackMode;
//- (void)endHeldAndAnswerCall:(id)arg1;
//- (void)enteredBackgroundForAllCalls;
//- (void)enteredForegroundForCall:(id)arg1;
//- (void)enumerateCallsInvokingBlock:(id /* block */)arg1 forCallsPassingTest:(id /* block */)arg2;
//- (void)enumerateCallsWithOptions:(unsigned int)arg1 invokingBlock:(id /* block */)arg2 forCallsPassingTest:(id /* block */)arg3;
//- (id)frontmostAudioOrVideoCall;
//- (id)frontmostCall;
- (void)handleCallModelStateChanged:(id)arg1;
//- (void)holdActiveAndAnswerCall:(id)arg1;
//- (id)incomingCall;
//- (id)incomingCalls;
//- (id)incomingVideoCall;
//- (id)initWithDaemonDelegate:(id)arg1;
//- (BOOL)isAddCallAllowed;
//- (BOOL)isAmbiguous;
//- (BOOL)isEndAndAnswerAllowed;
//- (BOOL)isHardPauseAvailable;
//- (BOOL)isHoldAllowed;
//- (BOOL)isHoldAndAnswerAllowed;
//- (BOOL)isMergeable;
//- (BOOL)isSendToVoicemailAllowed;
//- (BOOL)isSwappable;
//- (BOOL)isTakingCallsPrivateAllowed;
//- (void)pullHostedCallsFromPairedHostDevice;
//- (void)pullRelayingCallsFromClient;
//- (void)pullThumperCallFromClientUsingInfo:(id)arg1 completion:(id /* block */)arg2;
//- (void)pushHostedCallsToPairedClientDevice;
//- (void)pushRelayingCallsToHost;
//- (void)pushRelayingCallsToHostWithSourceIdentifier:(id)arg1;
//- (void)resumeCall:(id)arg1;
//- (void)sendFieldModeDigits:(id)arg1;
//- (void)setCallModelState:(id)arg1;
//- (void)swapCalls;
//- (id)videoCallWithStatus:(int)arg1;

@end

As you can see, only left in a few functions and I was able to build and run.

Will
  • 1,718
  • 3
  • 15
  • 23
0
NSString *frameworkPath = @"/System/Library/PrivateFrameworks/TelephonyUtilities.framework"];
NSBundle *bundlePath = [NSBundle bundleWithPath: frameworkPath];
if ([bundlePath load]) {
    Class TUCallCenter = NSClassFromString(@"TUCallCenter");
    tucallCenter = [TUCallCenter sharedInstance];
}

This is how you load TUCallCenter instance dynamically with private frameworks.

Jas_meet
  • 366
  • 1
  • 20