业余时间研究了一下手机迅雷的嗅探功能,感觉很神奇。于是想自己动手做一个。
需求很简单:1.拦截并记录网页里所有的有.m3u8的链接 2.使用链接投屏到电视机

拦截网络请求

在iOS中,拦截网页的跳转URL可以使用webviewdelegate中相应的方法,但是拦截webview中的网络请求就不行了。这个时候就要用到今天的主角NSURLProtocol
本文只实现拦截网络部分NSURLProtocol 的使用。

  1. 实例化NSURLProtocol
    NSURLProtocol 不能直接使用需要继承子类去实例化。
    创建子类SechemaURLProtocol继承自NSURLProtocol

SechemaURLProtocol.h

1
2
3
4
5
6
7
8
9
#import <Foundation/Foundation.h>
#import "Constant.h"

FOUNDATION_EXTERN NSString *const HttpProtocolKey;
FOUNDATION_EXTERN NSString *const HttpsProtocolKey;

@interface SechemaURLProtocol : NSURLProtocol

@end

实现SechemaURLProtocol.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (void)startLoading{}
- (void)stopLoading{}
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSString *scheme = [[request URL] scheme];

if ([request.URL.absoluteString containsString:@".m3u8"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"showURL" object:request.URL.absoluteString];

}
// 判断是否需要进入自定义加载器
if ([scheme caseInsensitiveCompare:HttpProtocolKey] == NSOrderedSame ||
[scheme caseInsensitiveCompare:HttpsProtocolKey] == NSOrderedSame)
{
//看看是否已经处理过了,防止无限循环
if ([NSURLProtocol propertyForKey:kURLProtocolHandledKey inRequest:request]) {
return NO;
}
}

return YES;
}

canInitWithRequest 所有网络请求都会走这个方法,在这里分析所有URL并且将信息传递到其他类中。

webview的类中注册
[NSURLProtocol registerClass:[SechemaURLProtocol class]];

接收通知消息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showURL:) name:@"showURL" object:nil];

解析URL,并显示相应的URL

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
-(void)showURL:(NSNotification *)not{
NSString *string = not.object;
NSInteger count = [[not.object mutableCopy] replaceOccurrencesOfString:@"https://" // 要查询的字符串中的某个字符
withString:not.object
options:NSLiteralSearch
range:NSMakeRange(0, [not.object length])];
if (count > 1) {
[self.dic setObject:string forKey:string];
NSArray *arr = [string componentsSeparatedByString:@"https://"];

int current = 0;
for (int i = 0 ; i<arr.count; i++) {

current++;
if ([arr[i] length]==0) {
continue;
}
NSString *tmp=@"";
for (int j=0; j<arr.count; j++) {
if (j==current) {
tmp = [[tmp stringByAppendingString:@"https://"] stringByAppendingString:arr[j]];
}
}
if (tmp.length !=0) {
[self.dic setObject:tmp forKey:tmp];
}


}

}else
{
[self.dic setObject:string forKey:string];
}
[self.tableView reloadData];
if (self.backgroundView.hidden || self.leftcon.constant == UIScreen.mainScreen.bounds.size.width) {
[self.view bringSubviewToFront:self.btn];

[self.view bringSubviewToFront:self.backgroundView];
self.backgroundView.hidden = NO;

[UIView animateWithDuration:1 animations:^{
self.leftcon.constant = 0;
[self.view layoutIfNeeded];
}];
}
}

完整代码地址 Github
后续还把网页嗅探功能优化了一下,点击m3u8自动投屏到电视机。
其他还有一些小工具 投屏,WiFi切换等。
如有什么好的点子可以告诉我哦~