3

I'm developing a tweak through logos template from ios open dev, but I've been looking around all header files in existing frameworks and I'm not finding the correct header which have method that's called after someone make a phone call ? Does any one know which it is ? I'm trying to do something like "AskToCall" which is available in Cydia that prompts an UIAlertView when a phone call is made, exactly when green button is pressed.

Thank you!

Connor Pearson
  • 63,902
  • 28
  • 145
  • 142

3 Answers3

8

1) First you need to link against private framework CoreTelephony: in your logos project's Makefile make sure you include yourprojectname_PRIVATE_FRAMEWORKS = CoreTelephony. Also make sure your MobileSubstrate .plist file filters "com.apple.mobilephone"

2) The phone application on iPhone uses CoreTelephony's CTCallDialWithID function to make calls. You can simply hook the function and do your thing instead.

#import "substrate.h" // for MSHookFunction definition

extern "C" void CTCallDialWithID(NSString *numberToDial); // function declaration

static void (*original_CTCallDialWithID)(NSString *numberToDial); //define a function pointer on which you'll assign the original call later

static void replaced_CTCallDialWithID(NSString *numberToDial){
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Verify New Call" message:[NSString stringWithFormat:@"Are you sure you want to call %@",numberToDial]
                         delegate:YOUR_OBJECT cancelButtonTitle:@"No" otherButtonTitles:@"Yes,please",nil];
    [alert show];
    [alert release];
}

In your constructor :

%ctor{
      %init();
      MSHookFunction((void *)CTCallDialWithID,(void *)replaced_CTCallDialWithID,(void **)&original_CTCallDialWithID);
      // Replace original function implementation with your replaced_ one.

}

To actually dial the number eventually (e.g. in your alertview's delegate.) after you've replaced the function implementation, use

CTCallDial(NSString *number);

because CTCallDialWithID expects {...} parameters and will not function correctly.

Note that this is a global hook in Phone.app for CTCallDialWithID (i works for all outgoing calls , including tapping a recent call to dial it, or a favorite, etc.

If you simply need a hook for just when pressing the Call button:

%hook DialerController
-(void)_callButtonPressed:(id)pressed{

   UIView *dialerView=MSHookIvar<UIView *>(self,"_dialerView");
   UILabel *lcd=MSHookIvar<UILabel *>(dialerView,"_lcd");
   NSString *numberToBeDialed=[lcd text];

  // do your thing with the number in here.
}
%end

I noticed you mentioned you found this method earlier and didn't work. It probably didn't work for you because you're not injecting in MobilePhone.app.

Your .plist file in your theos project should look like:

Filter = { Bundles = ("com.apple.mobilephone");};
Elias Limneos
  • 930
  • 9
  • 13
  • Thats great !!! thank u !!!! thats what i've been looking for !! everything its working fine right not except that i can't actually call the number ! – Pablo Alejandro Junge Oct 28 '12 at 21:24
  • How can i implement here the UIAlarView delegate buttonClickedAtIndex ?? – Pablo Alejandro Junge Oct 28 '12 at 21:25
  • 1
    Pablo, to call the number, in both of the above cases, either with DialerController or hooking the function, you can just do CTCallDial((NSString *)theNumber); You should declare it first like extern "C" void CTCallDial (NSString *number); – Elias Limneos Oct 29 '12 at 22:12
  • To implement the delegate method, save the number to a static variable or assign it to a property of an object of yours ([myobject sharedInstance] setOutgoingNumber:number] inside the hook; then in the delegate call , if (buttonIndex==1) { CTCallDial(self.outgoingNumber) ; } – Elias Limneos Oct 30 '12 at 21:39
1

To do that you would have to dump the MobilePhone.app (Located in /Applications/MobilePhone.app) headers from the filesystem an iPhone or decrypted ipsw files, then you would have to go through THOSE headers. You are bound to find what you are looking for there. To dump the headers you would need class-dump or class-dump-z (Preferred) from this repo:

ininjas.com/repo/

Then you would have to install Mobile Terminal (From Cydia) and run

class-dump-z -H /Applications/MobilePhone.app/MobilePhone -O /var/mobile/somefolder (This should work on an iPod touch 4 too)

To get the headers in /var/mobile/somefolder

Then you would have to put all the headers in /var/theos/include/MobilePhone (Wherever your theos folder is, in my case on my device therefore /var/theos/include)

After that you have to add the line

#import <MobilePhone/MobilePhone.h>

in your tweak.xm

s6luwJ0A3I
  • 1,023
  • 1
  • 9
  • 22
  • perfect, got the headers the way you said. Now i found the method - (void)_callButtonPressed:(id)pressed in the DialerController.h, but's not working anyway... do you know which header has that called method when the user taps on the green call button ? – Pablo Alejandro Junge Oct 26 '12 at 23:02
0

OK, hopefully I am understanding your question.

You simply want to display an alert popup saying "Really make phone call?" with Yes and No button.

This is how you would go about doing it:

// View Controller Header File (.h file)
@interface MyViewController <UIAlertViewDelegate>
{
    UIButton *callButton;
}

// View Controller Implementation File (.m file)
-(void)viewDidLoad
{
    ...
    [callButton addTarget:self selector:@selector(confirmCall) forControlEvent:UIControlTouchUpInside];
    ...
}

-(void)confirmCall
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirm Call" 
                                                    message:@"Really make call?" 
                                                   delegate:self 
                                          cancelButtonTitle:@"No" 
                                          otherButtonTitles:@"Yes", nil
                          ];
    [alert show];
    [alert release];
}

// UIAlertViewDelegate callback method
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // ---------------------------------------------------------------------------
    // Alert view button indexes starts from 0 (left most button) 
    // and increments for the next button.
    //
    // In our case, "No" button would have index 0 because it is the first button
    // followed by the "Yes" button having an index 1
    //
    // So what we're saying below is if user presses on the "Yes" button
    // for an alert that has the title "Confirm Call", then call that number
    // ---------------------------------------------------------------------------
    if([alertView.title isEqualToString:@"Confirm Call"] && buttonIndex == 1)
    {
        [self callNumber];
    }
}

-(void)callNumber
{
    NSString *rawNumber = [[NSString alloc] initWithString:@"+61 8 9123 4567"];
    NSString *cleanedString = [[NSString alloc] initWithString:[[rawNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:@"0123456789-+()"] invertedSet]] componentsJoinedByString:@""]];

    NSString *escapedPhoneNumber = [[NSString alloc] initWithString:[cleanedString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSString *properPhoneNumber = [[NSString alloc] initWithFormat:@"tel://%@",escapedPhoneNumber];

    NSURL *telURL = [[NSURL alloc] initWithString:properPhoneNumber];

    // prevent non phone iOS device from trying to making calls (iPod, iPad)
    if([[UIApplication sharedApplication] canOpenURL:telURL])
    {
        // make call now
        [[UIApplication sharedApplication] openURL:telURL];
    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Device Cannot Call" 
                                                        message:@"This device cannot make phone calls. Would you like to send an email instead ?" 
                                                       delegate:self 
                                              cancelButtonTitle:@"No" 
                                              otherButtonTitles:@"Yes", nil];
        [alert show];
        [alert release];
    }

    [telURL release];
    [properPhoneNumber release];
    [escapedPhoneNumber release];
    [cleanedString release];
    [rawNumber release];
}
Zhang
  • 11,549
  • 7
  • 57
  • 87
  • This isn't what the question is looking for, unfortunately. He wants to know how to get notified when a call is initiated from the Phone app, and inject his code there. – Nate Oct 26 '12 at 22:34
  • OK. Doesn't Apple have a thing with third party apps interfering with system events such as receiving a phone call? Using a private framework would prevent the app from being approved by Apple. – Zhang Oct 27 '12 at 12:34
  • the question did mention Cydia, and used the *jailbreak* tag, so we can assume this is not for the iTunes App Store – Nate Oct 27 '12 at 22:41