前言
在Android Cronet 构建 中讲了 Android 上 Cronet 的下载、编译、使用。
今天来说一说 iOS 上如何编译与使用。
下载
依旧先来看下 iOS 中如何下载,下载和 Android 一样,我这里直接给出需要执行的指令。
1
2
3
4
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH = " $PATH : $( pwd ) /depot_tools" # 设置环境变量,可以写到 .bashrc 中,这样就不用每次都执行一遍
mkdir ~/chromium && cd ~/chromium
fetch --no-history ios
最重要的是需要配置代理,一个好的代理能省非常多事情。
切换tag
切换分支是我在 iOS 上花费非常多时间才搞定的,再次强调,一个好的代理能省非常多事情。
切换 tag 也和 Android 类似,这里也直接给出需要执行的指令。
1
2
3
4
5
6
7
8
9
10
git fetch origin 95.0.4638.50
git checkout FETCH_HEAD
git switch -c 95.0.4638.50
COMMIT_DATE = $( git log -n 1 --pretty= format:%ci)
cd ~/depot_tools
git checkout $( git rev-list -n 1 --before= " $COMMIT_DATE " main)
export DEPOT_TOOLS_UPDATE = 0 # 禁用 depot_tools 自动更新
cd ~/chromium/src
git clean -ffd # 清空git工作目录,以免发生冲突
gclient sync -D --force --reset --with_branch_heads
在执行 git fetch origin 95.0.4638.50 的时候碰到一直下载不下来的问题,我在这里卡了一个星期。最后用下面这种办法解决的,仅供参考
1
2
3
4
git fetch --unshallow
git fetch origin 95.0.4638.50
git checkout FETCH_HEAD
git switch -c 95.0.4638.50
也就是多执行了一步 git fetch --unshallow ,接下来拉取 95.0.4638.50 就非常快了。
编译
iOS 编译与 Android 大体相同,只是有区分模拟器和真机。
默认编译出来的是给模拟器使用的,如果需要编译给真机使用需要加上 -i 选项,如下所示
真机-Release
1
2
3
cd ~/chromium/src
./components/cronet/tools/cr_cronet.py gn -i -r
ninja -C out/Release-iphoneos cronet_package
-i 的意思就是 iphoneos ,也就是给真机使用的
-r 也就是构建 Release 版本,这个和 Android 一样,也可以使用 --release
模拟器
模拟器就不需要加 -i 参数了
1
2
3
cd ~/chromium/src
./components/cronet/tools/cr_cronet.py gn -r
ninja -C out/Release-iphonesimulator cronet_package
使用 cr_cronet.py 的时候不要加 build 参数,会碰到如下错误
1
Error: no mobile provisioning profile found for "org.chromium.gtest.cronet-test".
示例
编译完之后,在 out/Release-iphonesimulator 目录下会有一个 all.xcodeproj 的文件,双击就可以使用 Xcode 打开了。
示例的代码在 src/components/cronet/ios 下,有关 Cronet 的初始化在子目录 cronet_consumer 之中,来看下 Cronet 初始化代码
src/components/cronet/ios/cronet_consumer/cronet_consumer_app_delegate.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- ( BOOL ) application: ( UIApplication * ) application
didFinishLaunchingWithOptions: ( NSDictionary * ) launchOptions {
[ Cronet setUserAgent : @"Dummy/1.0" partial : YES ];
[ Cronet setQuicEnabled : YES ];
[ Cronet start ];
[ Cronet startNetLogToFile :[ self currentNetLogFileName ] logBytes : NO ];
NSURLSessionConfiguration * config =
[ NSURLSessionConfiguration ephemeralSessionConfiguration ];
[ Cronet installIntoSessionConfiguration : config ];
NSString * chromiumPrefix = @"www.chromium.org" ;
[ Cronet setRequestFilterBlock : ^ BOOL ( NSURLRequest * request ) {
BOOL isChromiumSite = [[[ request URL ] host ] hasPrefix : chromiumPrefix ];
return ! isChromiumSite ;
}];
self . window = [[ UIWindow alloc ] initWithFrame :[[ UIScreen mainScreen ] bounds ]];
self . viewController =
[[ CronetConsumerViewController alloc ] initWithNibName : nil bundle : nil ];
self . window . rootViewController = self . viewController ;
[ self . window makeKeyAndVisible ];
return YES ;
}
由于 cronet 在 iOS 上会对网络请求进行 HOOK 所以之前该怎么用的就怎么用,接入成本就很低了。相比之下 Android 的接入成本就比较高了,因为大部分 Android 的网络请求会使用 OkHttp 或者 Retrofit 而不是 HttpURLConnection 。
使用
看了 cronet 提供的示例,我们也来写一个 Demo 看看。
使用 Xcode 创建一个新项目,然后把编译好的 Cronet.framework 拖动到项目中, Cronet.framework 在 out/Release-iphonesimulator/cronet/Cronet.framework
只放到项目中还不够,还需要在 targets -> General -> Frameworks,Librarys, and Embedeed Content 中找到 Cronet.framework 在 Embed 中改为 Embed & Sign 选项
接下来需要配置 Cronet ,在 AppDelegate.m 中加入如下代码
1
2
3
4
5
6
7
#import <Cronet/Cronet.h>
- ( BOOL ) application: ( UIApplication * ) application didFinishLaunchingWithOptions: ( NSDictionary * ) launchOptions {
[ Cronet setUserAgent : @"CronetDemo/1.0" partial : YES ];
[ Cronet setQuicEnabled : YES ];
[ Cronet start ];
return YES ;
}
接着在 ViewCrontroller.m 中加入网络请求代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- ( void ) viewDidLoad {
[ super viewDidLoad ];
[ self loadRequest ];
}
- ( void ) loadRequest {
NSURL * url = [ NSURL URLWithString : @"https://httpbin.org/get" ];
NSURLRequest * request = [ NSURLRequest requestWithURL : url ];
NSURLSession * session = [ NSURLSession sharedSession ];
NSURLSessionDataTask * dataTask = [ session dataTaskWithRequest : request completionHandler : ^ ( NSData * _Nullable data , NSURLResponse * _Nullable response , NSError * _Nullable error ) {
NSLog ( @"response %@" , response );
}];
[ dataTask resume ];
}
执行之后就可以看到在控制台打印了请求的信息。
碰到的错误
1
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
在终端中执行如下代之后解决
1
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
参考