zoukankan      html  css  js  c++  java
  • 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);

    }

  • 相关阅读:
    Java 注解指导手册(下)
    CentOS安装Redis Sentinel HA集群
    EasyBCD安装CentOS双系统
    读《大型网站技术架构核心原理与案例分析》
    CentOS的Redis内存分配策略配置
    CentOS搭建VSFTP
    freemaker分页备忘
    jenkins持续集成配置备忘
    Redis常用命令
    stream转byte数组几种方式
  • 原文地址:https://www.cnblogs.com/qq378829867/p/4137928.html
Copyright © 2011-2022 走看看