- PVSM.RU - https://www.pvsm.ru -
У меня появилась задача позвонить с iPhone на iOS7. На предыдущих версиях iOS (6 и ранее) было достаточно воспользоваться private API и все работало, но на iOS7 этот подход перестал работать. В этом посте я хочу рассказать как сделать звонок и получить собственный номер телефона из приложения.
Первым делом, что бы все работало необходимо сделать Jailbreak. Для последней версии iOS 7.1.2 он отлично делается с помощью en.pangu.io — jailbreak tool [2] Инструкцию по jalibreak можно посмотреть, например, здесь [3]. Я проделал это с iPhone4, iOS 7.1.2 на Windows 8.1 После того, как сделан jailbreak устанавливаем OpenSSH через Cydia.
Заходим на iPhone по ssh и меняем пароль для root [default password: alpine]
$ssh root@10.231.65.56
$passwd
Телефон готов. Подготовим приложение, которое будет звонить. В приложении мы будем использовать следующие private APIs:
void CTCallListDisconnectAll(); // for ending call header: CTCall.h
CTCallRef CTCallDial(CFStringRef number); // for calling header: CTCall.h
CFStringRef CTSettingCopyMyPhoneNumber(); // for getting own number header: CTSetting.h
Заголовочные файлыCTCall.h, CTSetting.h можно найти в репозитории на GitHub [4]
Теперь рассмотрим код, который без проблем работает на iOS 6.1.4 и без jailbreak.
- (IBAction)onPlaceCall:(id)sender {
NSString *numberToCall = [self.tfNumberToCall text];
NSLog(@"Open CoreTelephony");
void *ptrCoreTelephone = dlopen("/System/Library/Framework/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
if (ptrCoreTelephone == nil){
NSLog(@"ptrCoreTelephone is nil");
return;
}
NSLog(@"Get CTCallDial from CoreTelephony");
int (*pCTCallDial)(NSString*) = dlsym(ptrCoreTelephone, "CTCallDial");
if (pCTCallDial != nil) {
int error = pCTCallDial(numberToCall);
NSLog(@"pCTCallDial error: %d", error);
}
NSLog(@"Close CoreTelephony");
dlclose(ptrCoreTelephone);
}
- (IBAction)onStopCall:(id)sender {
NSLog(@"onStopCall");
void *ptrCoreTelephone = dlopen("/System/Library/Framework/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
if (ptrCoreTelephone == nil){
NSLog(@"ptrCoreTelephone is nil");
return;
}
NSLog(@"Get CTCallListDisconnectAll from CoreTelephony");
int (*pCTCallListDisconnectAll)() = dlsym(ptrCoreTelephone,
"CTCallListDisconnectAll");
if (pCTCallListDisconnectAll != nil) {
int error = pCTCallListDisconnectAll();
NSLog(@"pCTCallListDisconnectAll error: %d", error);
}
dlclose(ptrCoreTelephone);
}
-(NSString*) getMyNumber {
NSLog(@"Open CoreTelephony");
void *lib = dlopen("/Symbols/System/Library/Framework/CoreTelephony.framework/CoreTelephony",RTLD_LAZY);
NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
NSString* (*pCTSettingCopyMyPhoneNumber)() = dlsym(lib, "CTSettingCopyMyPhoneNumber");
NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
if (pCTSettingCopyMyPhoneNumber == nil) {
NSLog(@"pCTSettingCopyMyPhoneNumber is nil");
return nil;
}
NSString* ownPhoneNumber = pCTSettingCopyMyPhoneNumber();
dlclose(lib);
return ownPhoneNumber;
}
Теперь самое интересное. Этот же код будет работать на iOS7 если добавить entitlements приложению и переподписать его с этими entitlements. Для этого нужно проделать следующее.
Для этого нужно в XCode в Build Settings выставить следующее:
P
Затем запуситить сборку.
Нужно создать файл со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.coretelephony.Calls.allow</key>
<true/>
<key>com.apple.coretelephony.Identity.get</key>
<true/>
</dict>
</plist>
com.apple.coretelephony.Calls.allow — для звонков
com.apple.coretelephony.Identity.get — для получения номера
Положить его нужно в тоже место, откуда будет запущена команда подписи.
Для подписи нам понадобиться папка с бинарниками. Понять, куда их кладет XCode, можно запустив команду:
$ls -la ~/Library/Developer/Xcode/DerivedData/ | grep JBCall
Путь будет примерно таким:
/Users/username/Library/Developer/Xcode/DerivedData/JBCall-cktasembftvbmqaaiiunvljdwocs/Build/Products/Debug-iphoneos/JBCall.app
Копируем JBCall.app в отдельную папку, кладем рядом сней entitlements.xml:
JBCall.app
entitlements.xml
Теперь нужно подписать бинарники следующей командой:
$codesign --sign='iPhone Developer: FirstName SecondName (XXXXXXXX)’ --entitlements entitlements.xml JBCall.app
iPhone Developer: FirstName SecondName (XXXXXXXX) — название сертификата, котоырй можно посмотреть в keychain.
После проделанных действий можно установить приложение и пользоваться. В данном случае установка заключается в копировании папки *.app на iPhone и перезапуск SpringBoard. Я сделал это через scp в скрпте:
DST_DIR='/Applications'
APP_NAME='JBCall.app'
USER='root'
PASSWD='mypass'
IP='10.231.65.56'
APP_ON_MAC="/Users/username/Library/Developer/Xcode/DerivedData/JBCall-cktasembftvbmqaaiiunvljdwocs/Build/Products/Debug-iphoneos/JBCall.app"
sshpass -p $PASSWD scp -r $APP_NAME $USER@$IP:$DST_DIR
В скрипте нужно поменять только значения переременных под себя и можно запускать. Путь тоже нужно обновить:
/Users/username/Library/Developer/Xcode/DerivedData/JBCall-cktasembftvbmqaaiiunvljdwocs/Build/Products/Debug-iphoneos/JBCall.app
Перезапуск SpringBoard:
$sshpass -p $PASSWD ssh $USER@$IP su mobile -c uicache 1>/dev/null 2>&1
Отдельная команда перезапуска с девайса:
$su mobile -c uicache 1>/dev/null 2>&1
Конечно должны быть установлены sshpass и scp.
Все описанные действия по установки оформлены в виде скрипта [5]
Все, теперь приложение может звонить, класть трубку, показывать номер телефона.
В итоге мы получили приложение, которое звонит на последней версии iOS с jailbreak. Надеюсь кому-нибудь пригодиться данный опыт.
Спасибо ползователю creker [6] на stackoverflow [7] за подсказку о entitlements, которая была им обнаружена в файле:
/System/Library/CoreServices/SpringBoard.app/SpringBoard
Действительно, взглянув на бинарник можно найти текстовые строки:
com.apple.coretelephony.Calls.allow
com.apple.coretelephony.Identity.get
Автор: AMDev
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka-pod-ios/67539
Ссылки в тексте:
[1] Код проекта на github: https://github.com/0x8BADFOOD/iOS7-makecall-sample
[2] en.pangu.io — jailbreak tool: http://en.pangu.io/
[3] здесь: http://yablyk.com/883645-kak-sdelat-dzhejlbrejk-ios-7-1-2-pri-pomoshhi-utility-pangu-dlya-mac-i-windows/
[4] репозитории на GitHub: https://github.com/Cykey/ios-reversed-headers
[5] скрипта: https://github.com/0x8BADFOOD/iOS7-makecall-sample/blob/master/install_app.sh
[6] creker: http://stackoverflow.com/users/2363866/creker
[7] stackoverflow: http://stackoverflow.com/questions/18955156/ios-7-alternative-to-ctcall/19128719#19128719
[8] Инструкция для Jailbreak: http://yablyk.com/883645-kak-sdelat-dzhejlbrejk-ios-7-1-2-pri-pomoshhi-utility-pangu-dlya-mac-i-windows
[9] Источник: http://habrahabr.ru/post/233295/
Нажмите здесь для печати.