前言

公司内部有一给自己的 App 发布后台,类似于 FIR 那样的存在, 有完整的 LDAP 账号登录。每天的 daily build 和 历史发布版都会放到那里去。然而每次都要登录后台扫描二维码下载实在是太麻烦了,我们就打算做一个客户端。

于是问题来了:如何知道我手机上安装的礼物说版本号比我当前的要低呢?

方案们

方案一 剪贴板共享

我们知道同一个证书下的软件,是可以共享剪贴板的,所以我们可以把礼物说的版本号丢到剪贴板里存下来。

但问题在于:

  1. 礼物说要运行过

  2. 致命伤:必须同一个 账号的 证书,内部 APP 肯定会去用企业证书,而礼物说可能是线上证书,可能是企业证书。

所以这个方案被否掉了。

方案二 URLScheme

把礼物说的 URLScheme 写成 GiftTalk233 这样的方案,然后在项目中 CanOpenURL 确认安装。

当问题在于:

iOS 9 之后,CanOpenURL 的白名单有上限,而且要修改编译脚本过于麻烦,这个方案也被否掉了。

于是,常规方案都不可行,那么要祭出大杀器了,私有 API

私有 API

毕竟是内部使用的 APP,所以用用私有 API 也没有什么问题。经过查阅越狱开发的文档,我们发现了这么一个私有库:MobileInstallation.framework

使用起来还是蛮方便的,直接:

CFDictionaryRef dict = MobileInstallationLookup(NULL);
NSLog(@"%@", (NSDictionary*) dict);

然而,这个库正常情况下是不会被 Link 进来的,于是我们该怎么做呢?

链接私有库

经过前几篇文章,我们知道动态链接库都是写在 Mach-O 的头部。然而它最终是经过 unix 的一个系统函数 dlopen 来加载的,这货是可以突破沙盒环境的,不信你可以给 dlopen 下个断点看看。所以我们可以手动调用 dlopen 加载想要的私有库。

void* libHandle = dlopen("/System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation",RTLD_NOW);if (libHandle) {NSLog(@"加载成功!");
}

但是对于 C 语言函数来说,他在编译时就被换成了对应的函数指针,所以我们想调用上述方法并没有那么容易。而如果是 OC 的方法的话,我们直接通过 runtime 就可以拿到对应的结果了。

所以现在我们需要拿个函数指针做个映射:

这样就可以了!

然鹅,我拿这个这个东西去给同事得瑟的时候,被打脸了。

我拿了一台公司的 iPhone 4 iOS 7 做的开发,这个工作一切正常。但 iOS 8 以上,func 取不到。吓得我赶紧去 Github 上看头文件。

https://github.com/MP0w/iOS-Headers/blob/master/iOS8.1/PrivateFrameworks/MobileInstallation/MIInstallerClient.h

惊了个呆,iOS 8 居然重写了这个 framework,但仔细观察了一下,貌似有一个方法是我们想要的:

 - (void)fetchInstalledAppsWithOptions:(id)arg1 completion:(CDUnknownBlockType)arg2

好吧,我之前树的 Flag 应验了,那就 iOS 8 以上换一个写法吧。

真机运行得到:

required to have an entitlement named “com.apple.private.mobileinstall.allowedSPI” with an array containing “CopyInstalledAppsForLaunchServices” to call the MobileInstallation SPI

Wut?

entitlement.plist

若你对 iOS 签名机制了机的话,entitlement 绝对不陌生。不过我相信大多数开发者都很少和他打交道,这里我来简单说一下。

我们都知道签名需要证书的 profile 文件,而 entitlement 是一个授权机制,他里面约定了很多 iOS 的更高级的权限。有点像 Android 写在 manifest 里面的 permission。

比如:

  • 访问 HealthKit 需要添加 com.apple.developer.healthkit

  • 使用 Network Extension 查找 WI-FI 需要添加 com.apple.developer.networking.HotspotHelper

但是,这个是需要苹果授权的,且与 profile 对应的。于是我们想在 entitlement 里面添加 com.apple.private.mobileinstall.allowedSPI 是没问题,但是是无法通过签名,会提示找不到对应的 profile。

于是我们想调用私有的 entitlement 的话,越狱设备可以随便搞,但不越狱的话开发者层面是没有什么可以绕过去的方法 (但做安全的蒸米大大说其实是有解的,若有朋友知道欢迎留言)。

仿佛走入了死胡同

柳暗花明又一村

我们都知道同步推是有企业证书版本的,且能查看我们本地的全部 APP。于是,我们对着他们的代码找一下呗~

经过一番查找,我们定位到了一个叫做 ApplicationManager 的类,这个 loadInstalledApplications 的方法很抢眼

然后在逻辑结构中可以看到:

他很鸡贼的判断了一下系统版本是不是大于 8.0,如果不是,就用左边的 MobileInstallation.framework 来做,否则调用了一个方法,叫做 suoyouyianzhuangdeyingyong 。我能吐槽这名字么…

通过下面代码,我们可以发现一个类叫做 LSApplicationWorkspace 
在 Github 的私有头文件里面搜了一下,惊了个呆:

https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/MobileCoreServices.framework/LSApplicationWorkspace.h

他居然是 MobileCoreServices 的私有函数!我们连 dlopen 都省了。

于是,照猫画虎,我们有:

任务完成!

iOS 获取手机上已经安装的应用相关推荐

  1. 获取手机上已安装应用,游戏的安装包

    有些时候我们手机上安装好用的app,但后来找不到下载链接了,又想分享给好朋友,就可以用此应用将手机上安装的app安装包文件(.apk)保存到手机本地,然后用其他文件分享工具将安装包分享给好友安装,使用 ...

  2. charles安装证书并信任证书,仍然无法获取手机上的请求

    charles安装证书并信任证书,仍然无法获取手机上的请求,发生这种情况的时候请检查你的防火墙 手机安装证书的时候需要将手机连的WiFi保证跟电脑是同一个,并且先改成Charles提供的代理地址: 然 ...

  3. js判断手机上是否安装某APP

    前两天,产品给我又给我提了一个需求,就是给我看了一下人家的功能,说我们也想要这个功能,于是,我就开始实现这个功能了..... js判断手机上是否安装某APP,如果有的话直接打开App,否则打开App ...

  4. android 您的手机上未安装应用程序的解决方法

    android 创建桌面快捷方式的时候设置应用名称和图标是完全没有问题,但是点击快捷方式的时候出现"您的手机上未安装应用程序",这是快捷方式的执行目标设置错误,也就是启动Activ ...

  5. html5 判断是否安装app,js判断手机上是否安装app

    通过js进行判断,判断手机上是否安装某一app,因为js并不能操作手机原生的API,所以它判断的方法只是通过动态生成iframe,用它打开app,看能不能打开,通过这个时间进行判断,下面有两段代码: ...

  6. 你的手机上未安装应用程序”的解决方案

    最近开发了一个android程序,使用MyEclipse调试安装可以运行,退出重新点击我的App,结果老出现烦人的字眼"你的手机上未安装应用程序",我晕,你妹啊.网上搜索了一下,有 ...

  7. “你的手机上未安装应用程序”的解决方案

    最近开发了一个android程序,使用MyEclipse调试安装可以运行,退出重新点击我的App,结果老出现烦人的字眼"你的手机上未安装应用程序",我晕,你妹啊.网上搜索了一下,有 ...

  8. 怎样从一个手机上安两个不同版本的软件_一部手机上怎么安装两个不同版本的微信?一部手机安装两个不同版本微信的方法...

    一部手机上怎么安装两个不同版本的微信?一部手机安装两个不同版本微信的方法.很多朋友都不是很清楚,其实方法很简单的,下面小编就为大家介绍一下,一起来看看吧. 1.安卓微信双卡方法:准备工作 从上图我们可 ...

  9. 关于Android系统中“你的手机上未安装应用程序”问题

    有时候我们把写好的APK安装到Android系统中后,点击应用程序图标后程序并不运行,却提示"你的手机上未安装应用程序",这个问题多半是AndroidManifest.xml文件不 ...

最新文章

  1. Seaborn使用regplot函数可视化散点图并添加回归曲线以及回归线对应的置信区间(Scatter plot with regression line)
  2. 花5分钟过一遍jar包和war包的区别,以后都不会再迷茫
  3. 广东移动节能绿色数据中心掀起“能耗革命”
  4. centos7 go yum 安装_超详细的centos7下载安装Postgresql11(yum安装)教程
  5. java 二维数组_Java中二维数组和异常的内容及应用
  6. 使用alertmanager对监控对象进行报警(微信)三
  7. 【评分】第三次作业-团队展示
  8. jta mysql_JTA 使用 MySQL 分布式事务
  9. 在Linux下下载RPM包
  10. 收获,不止SQL优化——抓住SQL的本质--读过程
  11. 使用svm 对参数寻优的时候出现错误
  12. 你已经是台成熟的vivo手机了,要自己学会打王者
  13. Win9x 与 WinME 磁盘共享密码破解实战
  14. Amber分子动力学模拟
  15. 接触了阿里云国际版香港服务器,让我学会了飞一般的乐趣
  16. 大厂Android面试经历(已获头条、百度、OPPO等大厂offer)
  17. 项目运行时报错出现:因为在此系统上禁止运行脚本有关详细信息,请参阅 https。该如何解决
  18. [技术分享]-Servlet/tomcat/spring mvc之间关系
  19. 3-AltiumDesignerPCB设计
  20. 职场中最重要的情商,是管理情绪

热门文章

  1. python之深浅copy
  2. 什么是对象的深浅拷贝?怎么实现深浅拷贝?
  3. CF710F String Set Queries 三种解法
  4. 计算n=log2(N)
  5. 获取键盘通知的 UserInfo
  6. iOS9适配必看指南
  7. 高职高专专业目录与本科专业目录
  8. ZUCC 操作系统原理实验 模拟考试
  9. 抖音夜间模式怎么开启android,抖音怎么设置夜间模式
  10. 哪些是评副高职称需要具备的条件?副高职称申报条件你具备吗?