4

我尝试编写一个应用程序,它可以从网络服务器(ipa 文件)下载一个应用程序并安装它。有谁知道如何安装这个 ipa 文件?我可以在应用程序内使用 OTA 或使用命令行安装它吗?

4

2 回答 2

6

因此,这里有一个针对越狱设备的即时解决方案,它可以直接.ipa从您的应用程序中安装任何文件。您必须采取的步骤是:

I. 获得 root 访问权限。setuid(0);您可以通过从您的main()函数调用来实现此目的。您需要在可执行文件上设置粘性权限位并使用启动脚本。

二、解压缩.ipa文件。是的,没错——IPA 只是伪装的 ZIP 文件。您可以为此使用开源libzip库。

三、里面会有一个目录Payload。实际的应用程序包(我们称之为MyApp.app)将驻留在该文件夹中。

四。在文件系统的目录中创建一个目录/var/mobile/Applications。这将是要安装的应用程序的容器沙箱。按照惯例,这个目录的名字应该是一个 UUID。例如,您可以为此使用以下代码片段:

CFUUIDRef uuidObj = CFUUIDCreate(NULL);
CFStringRef uuid = CFUUIDCreateString(NULL, uuidObj);
CFRelease(uuidObj);

NSString *appPath = [@"/var/mobile/Applications" stringByAppendingPathComponent:(id)uuid];
[fmgr createDirectoryAtPath:appPath withIntermediateDirectories:YES attributes:nil error:NULL];
CFRelease(uuid);

五、通过Payload目录的内容循环找到app bundle(在第二步中获得)。将其复制到新创建的沙箱(其名称是 UUID 字符串)。还要复制iTunesMetadata.plistiTunesArtwork文件,以便 iTunes 为应用程序显示一个漂亮的图标并通知您更新。修复应用程序可执行文件的权限,使其可执行:

NSString *execName = [appInfoPlist objectForKey:@"CFBundleExecutable"];
NSString *execPath = [bundle stringByAppendingPathComponent:execName];
chmod(execPath.UTF8String, 0755);

六、您需要告诉 SpringBoard 找到您的应用程序,然后重新加载其已安装的应用程序缓存,以使新安装的图标出现在主屏幕上。为此,您首先更新 MobileInstallation 属性列表文件中的应用程序列表。这里的bundle变量是指应用程序包的文件系统位置,例如/var/mobile/applications/LONG_UUID_STRING/MyApp.app.

#define kMobileInstallationPlistPath @"/var/mobile/Library/Caches/com.apple.mobile.installation.plist"
NSMutableDictionary *appInfoPlist = [NSMutableDictionary dictionaryWithContentsOfFile:[bundle stringByAppendingPathComponent:@"Info.plist"]];
[appInfoPlist setObject:@"User" forKey:@"ApplicationType"];
[appInfoPlist setObject:bundle forKey:@"Path"];
[appInfoPlist setObject:@{
    @"CFFIXED_USER_HOME" : appPath,
    @"HOME" : appPath,
    @"TMPDIR" : [appPath stringByAppendingPathComponent:@"tmp"]
} forKey:@"EnvironmentVariables"];
[appInfoPlist setObject:appPath forKey:@"Container"];

NSData *data = [NSData dataWithContentsOfFile:kMobileInstallationPlistPath];
NSMutableDictionary *mobileInstallation = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:NULL error:NULL];
NSString *bundleID = [appInfoPlist objectForKey:@"CFBundleIdentifier"];
[[mobileInstallation objectForKey:@"User"] setObject:appInfoPlist forKey:bundleID];
[mobileInstallation writeToFile:kMobileInstallationPlistPath atomically:NO];

然后移除 SpringBoard 存储的缓存应用信息:

remove("/var/mobile/Library/Caches/com.apple.mobile.installation.plist");
remove("/var/mobile/Library/Caches/com.apple.springboard-imagecache-icons");
remove("/var/mobile/Library/Caches/com.apple.springboard-imagecache-icons.plist");
remove("/var/mobile/Library/Caches/com.apple.springboard-imagecache-smallicons");
remove("/var/mobile/Library/Caches/com.apple.springboard-imagecache-smallicons.plist");
remove("/var/mobile/Library/Caches/SpringBoardIconCache");
remove("/var/mobile/Library/Caches/SpringBoardIconCache-small");
remove("/var/mobile/Library/Caches/com.apple.IconsCache");

然后通知 SpringBoard 重新加载所有应用的列表:

Class __LSApplicationWorkspace = objc_getClass("LSApplicationWorkspace");
[(LSApplicationWorkspace *)[__LSApplicationWorkspace defaultWorkspace] invalidateIconCache:nil];
[(LSApplicationWorkspace *)[__LSApplicationWorkspace defaultWorkspace] registerApplication:[NSURL fileURLWithPath:bundle]];
notify_post("com.apple.mobile.application_installed");
于 2013-02-22T15:34:56.157 回答
2

您可以通过 OTA 分发执行此操作,请参阅 http://help.apple.com/iosdeployment-apps/mac/1.1/#app43ad871e

可以在此处找到示例 plist: https ://gist.github.com/hramos/774468

请注意,您要么需要 Enterprise Developer Program,要么收集用户的 UDID 并将它们包含在您的 ad-hoc 供应配置文件中。

于 2013-02-22T09:16:35.160 回答