您的位置:首页 > 移动开发

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

2017-04-30 01:46 375 查看
    上篇文章介绍了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);  //nessesary
AMDeviceCopyValue(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上面有一个开源相关代码, 可以借鉴一下。 

欢迎讨论
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios APP 安装