mac 自制app 打包安装工具(2)

来源:互联网 发布:mac window 编辑:程序博客网 时间:2024/06/06 04:30

    上篇文章介绍了xcodebuild的命令使用。

1.连接设备

这里本篇介绍如果连接手机, 安装app.

因为制作工具, 新建了一个mac app项目,导入需要使用的私有API,  MobileDevice.framework.

路径: /System/Library/PrivateFrameworks/MobileDevice.framework

这个文件是没有头文件,自己导入一下头文件MobileDevice.h  , 可以自己晚上找找,传送门

这里主要记录一下常用的几个接口, 注释也是比较详细。

mach_error_t AMDeviceNotificationSubscribe(am_device_notification_callback    callback, unsigned int unused0, unsigned int unused1, void* //unsigned int    dn_unknown3, struct am_device_notification **notification);

在当前线程注册一个函数, 有设备连接时, 会进行通知,

        struct am_device_notification *notify;        AMDeviceNotificationSubscribe(&device_callback, 0, 0, NULL, ¬ify);

回调方法:

void device_callback(struct am_device_notification_callback_info *info, void *arg) {        switch (info->msg) {        case ADNCI_MSG_CONNECTED:        {//device connect    info->dev            break;        }        case ADNCI_MSG_DISCONNECTED:{//device disconnect            break;        }        default:            break;    }}

设备连接和设备断开, info->dev获取设备的信息。 调用

CFStringRef AMDeviceCopyValue(struct am_device *device, uint32_t, CFStringRef cfstring);
获取设备信息, 参数分别为, 设备, 0, 关键字。

关键字在头文件里面有详细记录, 

例如获取设备名称, 在获取之前必须连接设备, 要不无法获取。网上的很多资料都没有查到, 坑了我不少时间。

AMDeviceConnect(dev);  //nessesaryAMDeviceCopyValue(dev, 0, CFSTR("DeviceName"));AMDeviceDisconnect(dev); //nessesary


2.安装

这里就直接贴代码了, CFStringRef的释放。容易内存泄露。

void handle_device(AMDeviceRef device) {    if (found_device) return; // handle one device only    CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier(device);    if (device_id != NULL) {        if(strcmp(device_id, CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding())) == 0) {            found_device = true;        } else {            return;        }    } else {        found_device = true;    }    CFRetain(device); // don't know if this is necessary?    printf("[  0%%] Found device (%s), beginning install\n", CFStringGetCStringPtr(found_device_id, CFStringGetSystemEncoding()));    AMDeviceConnect(device);    assert(AMDeviceIsPaired(device));    assert(AMDeviceValidatePairing(device) == 0);    assert(AMDeviceStartSession(device) == 0);    CFStringRef path = CFStringCreateWithCString(NULL, app_path, kCFStringEncodingASCII);    CFURLRef relative_url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false);    CFURLRef url = CFURLCopyAbsoluteURL(relative_url);    CFRelease(relative_url);    int afcFd;    assert(AMDeviceStartService(device, CFSTR("com.apple.afc"), &afcFd, NULL) == 0);    assert(AMDeviceStopSession(device) == 0);    assert(AMDeviceDisconnect(device) == 0);    assert(AMDeviceTransferApplication(afcFd, path, NULL, transfer_callback, NULL) == 0);      //安装操作回调函数    close(afcFd);    CFStringRef keys[] = { CFSTR("PackageType") };    CFStringRef values[] = { CFSTR("Developer") };    CFDictionaryRef options = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);    AMDeviceConnect(device);    assert(AMDeviceIsPaired(device));    assert(AMDeviceValidatePairing(device) == 0);    assert(AMDeviceStartSession(device) == 0);    int installFd;    assert(AMDeviceStartService(device, CFSTR("com.apple.mobile.installation_proxy"), &installFd, NULL) == 0);    assert(AMDeviceStopSession(device) == 0);    assert(AMDeviceDisconnect(device) == 0);    mach_error_t result = AMDeviceInstallApplication(installFd, path, options, install_callback, NULL);    if (result != 0)    {       printf("AMDeviceInstallApplication failed: %d\n", result);        exit(1);    }    close(installFd);    CFRelease(path);    CFRelease(options);    printf("[100%%] Installed package %s\n", app_path);    if (!debug) exit(0); // no debug phase    AMDeviceConnect(device);    assert(AMDeviceIsPaired(device));    assert(AMDeviceValidatePairing(device) == 0);    assert(AMDeviceStartSession(device) == 0);    printf("------ Debug phase ------\n");    mount_developer_image(device);      // put debugserver on the device    start_remote_debug_server(device);  // start debugserver    write_gdb_prep_cmds(device, url);   // dump the necessary gdb commands into a file    CFRelease(url);    printf("[100%%] Connecting to remote debug server\n");    printf("-------------------------\n");    signal(SIGHUP, gdb_ready_handler);    pid_t parent = getpid();    int pid = fork();    if (pid == 0) {        system(GDB_SHELL);      // launch gdb        kill(parent, SIGHUP);  // "No. I am your father."        _exit(0);    }}

//回调函数, 当前操作的状态,void transfer_callback(CFDictionaryRef dict, int arg) {    int percent;    CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status"));    CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent);    if (CFEqual(status, CFSTR("CopyingFile"))) {        CFStringRef path = CFDictionaryGetValue(dict, CFSTR("Path"));        if ((last_path == NULL || !CFEqual(path, last_path)) && !CFStringHasSuffix(path, CFSTR(".ipa"))) {            printf("[%3d%%] Copying %s to device\n", percent / 2, CFStringGetCStringPtr(path, kCFStringEncodingMacRoman));        }        if (last_path != NULL) {            CFRelease(last_path);        }        last_path = CFStringCreateCopy(NULL, path);        if (last_path != NULL) {            CFRelease(last_path);        }    }    CFRelease(dict);    CFRelease(status);}

void install_callback(CFDictionaryRef dict, int arg) {    int percent;    CFStringRef status = CFDictionaryGetValue(dict, CFSTR("Status"));    CFNumberGetValue(CFDictionaryGetValue(dict, CFSTR("PercentComplete")), kCFNumberSInt32Type, &percent);    printf("[%3d%%] %s\n", (percent / 2) + 50, CFStringGetCStringPtr(status, kCFStringEncodingMacRoman));    CFRelease(dict);}

2个关键点,设备和安装的app。
github上面有一个开源相关代码, 可以借鉴一下。 

欢迎讨论生气


0 0
原创粉丝点击