昨晚看一篇文章時看到了私有API這個詞,貌似開發者對私有API的使用很反感于是果斷百度谷歌,以下是Stackoverflow中關于Private Frameworks的一個解釋:
Private frameworks are frameworks which you are not allowed to use. They are not expected to be used outside of Apple, hence "Private". They are often lower-level libraries which may "break" the system if not used correctly. (But the frameworks have to exist because Apple's apps and public frameworks do use the private frameworks.)?
Since the private frameworks are not for public use, Apple doesn't need to give any headers or documentations away.
If you're writing for AppStore, you should not use private frameworks (unless you're from Apple). The system will immediately reject your app even before the review process begins.?
(On the other hand, for jailbroken platforms you're free to use any frameworks. Even so, the APIs of private frameworks is unstable, that you should avoid them if possible.?
There is an ongoing effort to document these private frameworks and API inhttp://iphonedevwiki.net/index.PHP/Main_Page.)
私有框架我們可以在SDK目錄中找到,詳細目錄如下:
- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/??
一大堆,里面就提供了私有API,這些私有框架蘋果并不提倡我們使用,私有框架中沒有給出頭文件(好像可以導出)而且也沒有官方的文檔說明,一旦app中使用了私有API,那么審核將無法通過(但是據說Google的GoogleVoice使用了私有API并且通過了審核,背后發生了什么我們不得而知)。但是私有API的功能貌似非常強大,更加是越獄開發的必備工具。
于是我很好奇地想玩下私有API,搜到了一個CoreTelephony框架,貌似在iOS?6以前該框架是私有框架,但來到iOS 7之后該框架絕對是個公開的框架了,因為我在PrivateFrameworks目錄下找不到該框架,相反在上一層中的Frameworks目錄下找到了該框架:

Apple官網也給出了該框架的文檔:Core Telephony Framework Reference
無論如何,先試玩下這個框架。
參考網上的一篇文章(10年寫的,那個時候CoreTelephony框架應該還是個私有框架吧),簡單使用了一下該框架,用來輸出手機的運營商信息和簡單的通話信息。
首先要導入CoreTelephony框架:
- ??
- @import?CoreTelephony;??
這里使用了@import關鍵字,所以要確保Enable Modules選項已經打開:

然后聲明一個CTCallCenter變量,該變量非strong屬性,所以不會導致在代碼塊中使用時形成retain cycle的問題:
- @interface?ViewController?()?{??
- ????CTCallCenter?*center_;???
- }??
- @end??
接著編寫獲取運營商信息的方法:
- -?(void)getCarrierInfo?{??
- ??????
- ????CTTelephonyNetworkInfo?*info?=?[[CTTelephonyNetworkInfo?alloc]?init];??
- ????CTCarrier?*carrier?=?info.subscriberCellularProvider;??
- ????NSLog(@"carrier:%@",?[carrier?description]);??
- ??????
- ??????
- ????info.subscriberCellularProviderDidUpdateNotifier?=?^(CTCarrier?*carrier)?{??
- ????????NSLog(@"carrier:%@",?[carrier?description]);??
- ????};??
- ??????
- ??????
- ????NSLog(@"Radio?Access?Technology:%@",?info.currentRadioAccessTechnology);??
- }??
最后在viewDidLoad方法中注冊通話事件的處理代碼塊:
- -?(void)viewDidLoad??
- {??
- ????[super?viewDidLoad];??
- ??????
- ??????
- ????[self?getCarrierInfo];??
- ??????
- ??????
- ????CTCallCenter?*center?=?[[CTCallCenter?alloc]?init];??
- ????center_?=?center;??
- ????center.callEventHandler?=?^(CTCall?*call)?{??
- ????????NSSet?*curCalls?=?center_.currentCalls;??
- ????????NSLog(@"current?calls:%@",?curCalls);??
- ????????NSLog(@"call:%@",?[call?description]);??
- ????};??
- }??
這里有一點比較奇怪,如果我不使用CTCallCenter的currentCalls屬性,那么將無法輸出代碼塊中的參數call的信息。
代碼很簡單,功能也很有限,下面真機調試下(模擬器輸出為null,這個不用解釋了吧)。
啟動程序,控制臺輸出信息如下:
- 2014-02-15?14:48:31.711?GetMyPhone[762:60b]?carrier:CTCarrier?(0x166682f0)?{??
- Carrier?name:?[中國移動]??
- Mobile?Country?Code:?[460]??
- Mobile?Network?Code:[07]??
- ISO?Country?Code:[cn]??
- Allows?VOIP??[YES]??
- }??
- 2014-02-15?14:48:31.713?GetMyPhone[762:60b]?Radio?Access?Technology:CTRadioAccessTechnologyEdge??
Radion Acess Technology的值包括:
- ?
- ?
- ??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyGPRS??????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyEdge??????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyWCDMA?????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyHSDPA?????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyHSUPA?????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyCDMA1x????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyCDMAEVDORev0??__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyCDMAEVDORevA??__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyCDMAEVDORevB??__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyeHRPD?????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
- CORETELEPHONY_EXTERN?NSString?*?const?CTRadioAccessTechnologyLTE???????????__OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0);??
以上信息指的是手機的數據業務吧,我的是Edge,不知道是什么,搜了一下:
GPRS:(General Packet Radio Service),它是GSM移動電話用戶可用的一種移動數據業務, 是GSM的技術升級,屬于2.5G,簡單講就是網速更快了。?
EDGE:(Enhanced Data Rate for GSM Evolution),即增強型數據速率GSM演進技術。 是GPRS的技術升級,屬于2.75G。?
EDGE和GPRS同屬于從GSM到3G的過渡技術。
之后另外拿臺手機打入本機,并且Descline,輸出如下:
- 2014-02-15?14:48:38.727?GetMyPhone[762:1803]?current?calls:{(??
- ????CTCall?(0x16620620)?{??
- callState:?[CTCallStateIncoming]??
- Call?ID:?[E3E1D27E-3644-4BE3-9748-5B835925EDC2]??
- }??
- ??
- )}??
- 2014-02-15?14:48:38.739?GetMyPhone[762:1803]?call:CTCall?(0x16620620)?{??
- callState:?[CTCallStateIncoming]??
- Call?ID:?[E3E1D27E-3644-4BE3-9748-5B835925EDC2]??
- }??
- 2014-02-15?14:48:42.684?GetMyPhone[762:1803]?current?calls:(null)??
- 2014-02-15?14:48:42.710?GetMyPhone[762:1803]?call:CTCall?(0x165267e0)?{??
- callState:?[CTCallStateDisconnected]??
- Call?ID:?[E3E1D27E-3644-4BE3-9748-5B835925EDC2]??
- }??
可以看到通話狀態由Incoming到Disconnected,在斷開通話時current calls變為nil了。
那么該app可不可以在后臺監控通話事件呢?答案是不行。
1.你可以讓手機進入后臺,然后用另外一臺手機打入本機,控制臺沒有關于通話信息的輸出。
2.你可以嘗試用本機打電話出去,此時我們調用了系統的Phone程序,Demo程序已經進入了后臺,無法監聽到任何通話信息。
3.用別的手機打入本機,選擇Answer(話費要錢,調試完不要忘記斷開通話啊),此時系統將調用Phone程序,Demo程序進入后臺,所以在控制臺輸出中我們找不到Disconnected的通知:
- 2014-02-15?14:47:07.946?GetMyPhone[751:3407]?current?calls:{(??
- ????CTCall?(0x16642820)?{??
- callState:?[CTCallStateIncoming]??
- Call?ID:?[140AF363-434D-41EE-BDC9-4730F5865724]??
- }??
- ??
- )}??
- 2014-02-15?14:47:07.959?GetMyPhone[751:3407]?call:CTCall?(0x16642820)?{??
- callState:?[CTCallStateIncoming]??
- Call?ID:?[140AF363-434D-41EE-BDC9-4730F5865724]??
- }??
- 2014-02-15?14:47:15.836?GetMyPhone[751:1807]?current?calls:{(??
- ????CTCall?(0x16563140)?{??
- callState:?[CTCallStateConnected]??
- Call?ID:?[140AF363-434D-41EE-BDC9-4730F5865724]??
- }??
- ??
- )}??
- 2014-02-15?14:47:15.855?GetMyPhone[751:1807]?call:CTCall?(0x16563140)?{??
- callState:?[CTCallStateConnected]??
- Call?ID:?[140AF363-434D-41EE-BDC9-4730F5865724]??
- }??
本文簡單使用了一下CoreTelephony這個曾經的私有框架,等以后真正用上私有API時再寫文章做下筆記吧。
Demo已上傳:點此進入下載頁
參考資料:
Core Telephony
What are Private FrameWorks and how will we use them?
Block的Retain Cycle的解決方法
@import vs #import - iOS 7
private framework使用(該文章給出了私有框架的路徑)