3

I am new to the jailbreak tweak development scene. I am trying to figure out the appropriate method to 'hook' so I can intercept an incoming call (and then run some code).

I have dumped the header files of CoreTelephony framework however no methods seem obvious to hook. I have tried:

- (void)broadcastCallStateChangesIfNeededWithFailureLogMessage:(id)arg1;
- (BOOL)setUpServerConnection;

but neither have worked. By worked I mean - get called when the iPhone receives a call.

Any pointers as to the appropriate method to hook? Thanks :)

Note: This is going to be a jailbreak tweak using private APIs so it won't be submitted to the App Store.

cud_programmer
  • 1,244
  • 1
  • 20
  • 37
  • Do you just need to get **notified** when a phone call comes in, or do you need to truly **intercept** the call that normally goes to the Phone app, so that you can replace some of the code that normally runs? Let me know if the difference is not clear, as I've described it. – Nate Feb 07 '13 at 21:58
  • It would work just being notified. I have since gone down this route using `[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callReceived:) name:CTCallStateIncoming object:nil];` but the "callReceived" method is not being called (ironic). I'll have a play around, it's probably something obvious! – cud_programmer Feb 07 '13 at 22:28
  • What do you need that for? – AlexWien Feb 08 '13 at 03:56

2 Answers2

2

I didn't test your code, but I think your problem might be that you need to use the Core Telephony notification center to register for that event (not what you had in the code in your comment). Something like this:

// register for all Core Telephony notifications
id ct = CTTelephonyCenterGetDefault();
CTTelephonyCenterAddObserver(ct,   // center
                             NULL, // observer
                             telephonyEventCallback,  // callback
                             NULL,                    // event name (or all)
                             NULL,                    // object
                             CFNotificationSuspensionBehaviorDeliverImmediately);

and your callback function is

static void telephonyEventCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
    NSString *notifyname = (NSString*)name;
    if ([notifyname isEqualToString:@"kCTCallIdentificationChangeNotification"])
    {
        NSDictionary* info = (NSDictionary*)userInfo;
        CTCall* call = (CTCall*)[info objectForKey:@"kCTCall"];
        NSString* caller = CTCallCopyAddress(NULL, call);

        if (call.callState == CTCallStateDisconnected)
        {
            NSLog(@"Call has been disconnected");
        }
        else if (call.callState == CTCallStateConnected)
        {
            NSLog(@"Call has just been connected");
        }
        else if (call.callState == CTCallStateIncoming)
        {
            NSLog(@"Call is incoming");
        }
        else if (call.callState == CTCallStateDialing)
        {
            NSLog(@"Call is Dialing");
        }
        else
        {
            NSLog(@"None of the conditions");
        }
    }
}

I offer another technique in this similar question here. Also, note my comment in that question about not getting the notifications in a UIApplication that has been put into the background.

Update: see cud_programmer's comment below about using kCTCallStatus on iOS 6 instead of kCTCall.

Community
  • 1
  • 1
Nate
  • 31,017
  • 13
  • 83
  • 207
  • Thanks @Nate, that indeed works. Quick question - if I display a simple `UIAlertView` when a call is incoming (so after or before your `NSLog(@"Call is incoming");` it doesn't get shown until after the call has ended (stop ringing). Is this because the main thread is being locked up dealing with the Phone app UI? Thanks :) – cud_programmer Feb 08 '13 at 10:28
  • @cud_programmer, Hmmm. That sounds likely (your app gets backgrounded when the Phone app takes over). Have you looked at my other answer that I linked to? It involves listening for phone calls in a *Launch Daemon*, which is a long-running background process. I'm wondering if you could detect the incoming call in a daemon, and choose to create your popup with [CFUserNotification](http://stackoverflow.com/a/10964582/119114) instead of `UIAlertView`. Is that an option for your app? – Nate Feb 08 '13 at 10:32
  • I have had a look over your linked answer and it was very helpful. I'll try it out and have a play around. Eventually, I don't need to show a UIAlertView just run some code (non UI to begin with) - but I just need it to execute immediately and concurrently when a call comes in – cud_programmer Feb 08 '13 at 10:50
  • 1
    @cud_programmer, so if you really don't need to perform UI operations, then it seems to me to make even more sense to build a **Launch Daemon**, that runs all the time. Then, you don't have to worry about all the restrictions iOS puts on normal UIApplications. The link to my other answer has a link to Chris Alvares' online tutorial for creating launch daemons. – Nate Feb 09 '13 at 00:06
  • I have implemented the code.. all works well apart from calling `call.callState` - it crashes springboard with the error message that callState is an "unrecognised selector". Do you know why this is the case? Thanks – cud_programmer Feb 23 '13 at 15:58
  • I don't know. [The Apple docs](http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/CTCall/Reference/Reference.html) say that `callState` is part of the public API, so it should be recognized. This stuff shouldn't require jailbreaking, so can you run this app in the debugger, and change the code to use this: `id call = [info objectForKey:@"kCTCall"];`? Then, look at the value of the `call` variable. Maybe it's changed, and is no longer a `CTCall` instance? What version of iOS did you see this problem on? – Nate Feb 23 '13 at 21:59
  • this is on iOS 6.1 - I have solved the problem by looking at `kCTCall` as you said. I have found "4" corresponds to incoming call (ringing). – cud_programmer Feb 23 '13 at 22:26
  • But, are you able to still use `call.callState == 4`? Or does `callState` still crash the program? – Nate Feb 23 '13 at 22:59
  • 1
    I'm using `[[[info objectForKey:@"kCTCallStatus"] stringValue] isEqualToString:@"4"]` and it works. `call.callState` still crashes the program. – cud_programmer Feb 23 '13 at 23:02
  • Does this program need to be actively open on screen to get the trigger when a user accepts a call? I read some answers like that in other question. – nanospeck Oct 15 '14 at 09:54
  • 1
    @nanospeck, unfortunately, `CTCallCenterAddObserver()` is not a public API, so that would probably get this rejected. However, [`CTCall` is public](https://developer.apple.com/LIBRARY/ios/documentation/NetworkingInternet/Reference/CTCall/index.html). So, there must now be some API that allows you to use it. – Nate Oct 15 '14 at 10:14
  • 1
    @nanospeck, Take a look [at this documentation ... this looks like a public replacement for my code above](https://developer.apple.com/library/ios/documentation/networkinginternet/reference/CTCallCenter/index.html#//apple_ref/occ/instp/CTCallCenter/callEventHandler). – Nate Oct 15 '14 at 10:18
  • The doc say "While it is suspended, your application does not receive call events.". So still I wont be able to receive call events when the app is not running in foreground. :( Thnx. – nanospeck Oct 15 '14 at 10:23
  • 1
    @nanospeck, if the docs used the word "suspended" specifically, make sure you understand [the different iOS app states clearly](http://www.techrepublic.com/blog/software-engineer/understand-the-states-and-transitions-of-an-ios-app/). If you're wanting an app that can **always get notified** and never suspends, there's a few ways to achieve that, but they probably wouldn't be accepted on the App Store. – Nate Oct 15 '14 at 10:52
  • `-[CTCallCenter callEventHandler]` and `-[CTCallCenter currentCalls]` do not appear to function in iOS 9.x – Beltalowda Jun 09 '16 at 16:13
0

Is it possible?

Yes.

Would a regular average person with no background in computer engineering or knowhow of how cell towers work be capable of something like this?

No.

Technically you can buy router looking thing to do this which aren’t cheap, are illegal and cellphone companies can actually track them down since it interferes with the network. So other than government agencies or international spies i don’t think you have anything to worry about. But if the government is exactly what you’re worried about well I’m sorry to tell you they’ve been doing a lot more then intercepting just phones

gv277
  • 1