IOS 使用動態庫(dylib)和動態加載framework


在iphone上使用動態庫的多為dylib文件,這些文件使用標准的dlopen方式來使用是可以的。那相同的在使用framework文件也可以當做動態庫的方式來動態加載,這樣就可以比較自由的使用apple私有的framework了。

dlopen是打開庫文件

dlsym是獲取函數地址

dlclose是關閉。

 

當然,要使用這種方式也是有明顯缺陷的,那就是你要知道函數名和參數,否則無法繼續。

私有庫的頭文件可以使用class dump的方式導出來,這個詳細的就需要google了。

下面是兩個使用的例子

1: 這是使用coreTelephony.framework獲取imsi

#define PRIVATE_PATH  "/System/Library/PrivateFrameworks/CoreTelephony.framework/CoreTelephony"

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
#if !TARGET_IPHONE_SIMULATOR
    void *kit = dlopen(PRIVATE_PATH,RTLD_LAZY);    
    NSString *imsi = nil;
    int (*CTSIMSupportCopyMobileSubscriberIdentity)() = dlsym(kit, "CTSIMSupportCopyMobileSubscriberIdentity");
    imsi = (NSString*)CTSIMSupportCopyMobileSubscriberIdentity(nil);
    dlclose(kit);    

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"IMSI" 
                                                    message:imsi 
                                                   delegate:self 
                                          cancelButtonTitle:@"OK" 
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
#endif
}

 

 

2:這是使用SpringBoardServices.framework來設置飛行模式開關

#ifdef SUPPORTS_UNDOCUMENTED_API
#define SBSERVPATH  "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
#define UIKITPATH "/System/Library/Framework/UIKit.framework/UIKit"

// Don't use this code in real life, boys and girls. It is not App Store friendly.
// It is, however, really nice for testing callbacks
+ (void) setAirplaneMode: (BOOL)status;
{
    mach_port_t *thePort;
    void *uikit = dlopen(UIKITPATH, RTLD_LAZY);
    int (*SBSSpringBoardServerPort)() = dlsym(uikit, "SBSSpringBoardServerPort");
    thePort = (mach_port_t *)SBSSpringBoardServerPort(); 
    dlclose(uikit);
    
    // Link to SBSetAirplaneModeEnabled
    void *sbserv = dlopen(SBSERVPATH, RTLD_LAZY);
    int (*setAPMode)(mach_port_t* port, BOOL status) = dlsym(sbserv, "SBSetAirplaneModeEnabled");
    setAPMode(thePort, status);
    dlclose(sbserv);
}
#endif

 

 

iphone SprintBoard部分私有API總結

 本文介紹iOS SrpintBoard框架的部分私有API,具體包括:

  • 獲取ios上當前正在運行的所有App的bundle id(不管當前程序是在前台還是后台都可以)
  • 獲取ios上當前前台運行的App的bundle id(不管當前程序是在前台還是后台都可以)
  • 根據ios app的bundle id得到其App名稱、圖標(不管當前程序是在前台還是后台都可以)
  • 直接通過App 的bundle id來運行該App,無需使用url scheme(僅限當前程序在前台時,假如程序在后台能隨便運行其他App,那就無敵了@_@)

(1)初始化

    void * uikit = dlopen("/System/Library/Framework/UIKit.framework/UIKit", RTLD_LAZY);

    int (*SBSSpringBoardServerPort)() =

    dlsym(uikit, "SBSSpringBoardServerPort");

    p = (mach_port_t *)SBSSpringBoardServerPort();

    dlclose(uikit);

    sbserv = dlopen(SBSERVPATH, RTLD_LAZY);

(2)獲取iphone上所有正在運行的app的bundle id列表

 

NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggablet) =

 

                    dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers");

 

NSArray *currentRunningAppBundleIdArray= SBSCopyApplicationDisplayIdentifiers(p,NO,YES);

 

(3)得到iphone 前台運行的app的bundle id

void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) = dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier");

char topapp[256];

SBFrontmostApplicationDisplayIdentifier(p,topapp);

currentTopAppBundleId=[NSStringstringWithFormat:@"%s",topapp];

(4)根據iphone app的bundle id得到其app名稱

 NSString * (*SBSCopyLocalizedApplicationNameForDisplayIdentifier)(NSString* ) =   dlsym(sbserv, "SBSCopyLocalizedApplicationNameForDisplayIdentifier");

 

NSString *strAppName = SBSCopyLocalizedApplicationNameForDisplayIdentifier(strBundleId);

 (5)根據iphone app 的bundle id得到其圖標

 NSData* (*SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString * bundleid) =

    dlsym(sbserv, "SBSCopyIconImagePNGDataForDisplayIdentifier");

    UIImage *icon = nil;

    NSData *iconData = SBSCopyIconImagePNGDataForDisplayIdentifier(bundleid);

    if (iconData != nil) {

        icon = [UIImage imageWithData:iconData];   

    }

    return icon;

 

(6)直接通過app 的bundle id來運行該app

 在ios中,一個app調起另一個app的方式通常是用url scheme,但是用這個 私有app,可以在不需要url scheme的情況下運行任何app

-(void)openAppByBundleId:(NSString*)bundleId

{

    void* sbServices = dlopen("/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices", RTLD_LAZY);

    int (*SBSLaunchApplicationWithIdentifier)(CFStringRef identifier, Boolean suspended) = dlsym(sbServices, "SBSLaunchApplicationWithIdentifier");

    const char *strBundleId = [bundleId cStringUsingEncoding:NSUTF8StringEncoding];

    int result = SBSLaunchApplicationWithIdentifier((__bridge CFStringRef)bundleId, NO);

    dlclose(sbServices);

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM