mPaas离线包之内网环境iOS客户端白页问题从入门到放弃
手机连不上内网已经解决了,
手机udid没加也解决了。
不得不说mPaas把h5容器封装的很死,即使完全知道本地h5如何在webview加载的,也很难查看其问题。
h5离线包只能加载从发布平台导出来的h5代码,即使想改,自己也改不了,改了,也得在发布平台重新发布才可以用。
如果是明文的h5自己就可以拦截替换一些文件,随便加点代码。
解决:修改h5代码(加点弹窗),发布h5代码,可能需要很多次,查看哪行代码没有执行下去。在蚂蚁的人不改客户端的情形下。
混淆后的一个js文件有300k,900k,xcode打开都直接卡死。
下面是客户端能看到的 混淆后的js小部分
2,0),a.maxY=-a.minY,a.touchesCurrent.x="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,a.touchesCurrent.y="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,!a.isMoved&&!i.isScaling){if(t.isHorizontal()&&(Math.floor(a.minX)===Math.floor(a.startX)&&a.touchesCurrent.x<a.touchesStart.x||Math.floor(a.maxX)===Math.floor(a.startX)&&a.touchesCurrent.x>a.touchesStart.x))return void(a.isTouched=!1);if(!t.isHorizontal()&&(Math.floor(a.minY)===Math.floor(a.startY)&&a.touchesCurrent.y<a.touchesStart.y||Math.floor(a.maxY)===Math.floor(a.startY)&&a.touchesCurrent.y>a.touchesStart.y))return void(a.isTouched=!1)}e.preventDefault(),e.stopPropagation(),a.isMoved=!0,a.currentX=a.touchesCurrent.x-a.touchesStart.x+a.startX,a.currentY=a.touchesCurrent.y-a.touchesStart.y+a.startY,a.currentX<a.minX&&(a.currentX=a.minX+1-Math.pow(a.minX-a.currentX+1,.8)),a.currentX>a.maxX&&(a.currentX=a.maxX-1+Math.pow(a.currentX-a.maxX+1,.8)),a.currentY<a.minY&&(a.currentY=a.minY+1-Math.pow(a.minY-a.currentY+1,.8)),a.currentY>a.maxY&&(a.currentY=a.maxY-1+Math.pow(a.currentY-a.maxY+1,.8)),n.prevPositionX||(n.prevPositionX=a.touchesCurrent.x),n.prevPositionY||(n.prevPositionY=a.touchesCurrent.y),n.prevTime||(n.prevTime=Date.now()),n.x=(a.touchesCurrent.x-n.prevPositionX)/(Date.now()-n.prevTime)/2,n.y=(a.touchesCurrent.y-n.prevPositionY)/(Date.now()-n.prevTime)/2,Math.abs(a.touchesCurrent.x-n.prevPositionX)<2&&(n.x=0),Math.abs(a.touchesCurrent.y-n.prevPositionY)<2&&(n.y=0),n.prevPositionX=a.touchesCurrent.x,n.prevPositionY=a.touchesCurrent.y,n.prevTime=Date.now(),s.$imageWrapEl.transform("translate3d("+a.currentX+"px, "+a.currentY+"px,0)")}}},onTouchEnd:function(){var e=this.zoom,t=e.gesture,i=e.image,s=e.velocity;if(t.$imageEl&&0!==t.$imageEl.length){if(!i.isTouched||!i.isMoved)return i.isTouched=!1,void(i.isMoved=!1);i.isTouched=!1,i.isMoved=!1;var a=300,n=300,r=s.x*a,o=i.currentX+r,l=s.y*n,d=i.currentY+l;0!==s.x&&(a=Math.abs((o-i.currentX)/s.x)),0!==s.y&&(n=Math.abs((d-i.currentY)/s.y));var c=Math.max(a,n);i.currentX=o,i.currentY=d;var p=i.width*e.scale,h=i.height*e.scale;i.minX=Math.min(t.slideWidth/2-p/2,0),i.maxX=-i.minX,i.minY=Math.min(t.slideHeight/2-h/2,0),i.maxY=-i.minY,i.currentX=Math.max(Math.min(i.currentX,i.maxX),i.minX),i.currentY=Math.max(Math.min(i.currentY,i.maxY),i.minY),t.$imageWrapEl.transition(c).transform("translate3d("+i.currentX+"px, "+i.currentY+"px,0)")}},onTransitionEnd:function(){var e=this.zoom,t=e.gesture;t.$slideEl&&this.previousIndex!==this.activeIndex&&(t.$imageEl.transform("translate3d(0,0,0) scale(1)"),t.$imageWrapEl.transform("translate3d(0,0,0)"),e.scale=1,e.currentScale=1,t.$slideEl=void 0,t.$imageEl=void 0,t.$imageWrapEl=void 0)},toggle:function(e){var t=this.zoom;t.scale&&1!==t.scale?t.out():t.in(e)},in:function(t){var i,s,a,n,r,o,l,d,c,p,h,u,v,m,f,g,y=this,w=y.zoom,b=y.params.zoom,C=w.gesture,S=w.image;C.$slideEl||(C.$slideEl=y.clickedSlide?e(y.clickedSlide):y.slides.eq(y.activeIndex),C.$imageEl=C.$slideEl.find("img, svg, canvas"),C.$imageWrapEl=C.$imageEl.parent("."+b.containerClass)),C.$imageEl&&0!==C.$imageEl.length&&(C.$slideEl.addClass(""+b.zoomedSlideClass),void 0===S.touchesStart.x&&t?(i="touchend"===t.type?t.changedTouches[0].pageX:t.pageX,s="touchend"===t.type?t.changedTouches[0].pageY:t.pageY):(i=S.touchesStart.x,s=S.touchesStart.y),w.scale=C.$imageWrapEl.attr("data-swiper-zoom")||b.maxRatio,w.currentScale=C.$imageWrapEl.attr("data-swiper-zoom")||b.maxRatio,t?(f=C.$slideEl[0].offsetWidth,g=C.$slideEl[0].offsetHeight,a=C.$slideEl.offset().le
客户端调用方法有限。
通过控制台的打印:在加载h5包时会有一些日志打印发现了两点
1.行为分析的外网js,通过MyConnectionURLProtocol拦截到外网的js链接地址,然后从整个工程扫描这个地址,发现是行为分析的framework里面的。
把他关掉:NBLogConfigurationGet().shouldInjectSPMJS = NO;
2.长链接:通过c语言hook系统日志打印方法nslog发现有几个日志是[DTLongLinkDataDispatch cmdTimeout:]打印出来的。
然后把他也关掉 [MySyncService sharedInstance]这个方法注释掉。
再然后控制台没有什么有用信息了。
开始的时候又写了一个MyConnectionURLProtocol。想拦截处理,但是蚂蚁内部已经有了一个PSDWebViewURLProtocol,这样两个都会走。那就把PSDWebViewURLProtocol的方法都hook过来吧
//
// PSDWebViewURLProtocol+YYY.h
//
//
// Created by YYY on 2019/9/10.
// Copyright © 2019 Alibaba. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface PSDWebViewURLProtocol:NSURLProtocol
@end
@interface PSDWebViewURLProtocol (YYY)
@end
NS_ASSUME_NONNULL_END
//
// PSDWebViewURLProtocol+YYY.m
//
//
// Created by YYY on 2019/9/10.
// Copyright © 2019 Alibaba. All rights reserved.
//
#import "PSDWebViewURLProtocol+YYY.h"
@interface PSDWebViewURLProtocol () <NSURLConnectionDataDelegate>
@property (nonatomic, strong) NSURLConnection * connection;
@property (nonatomic, assign) NSStringEncoding stringEncoding ;
@end
@implementation PSDWebViewURLProtocol (YYY)
+ (void)load
{
{
Method originalMethod = class_getClassMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(canInitWithRequest:));
Method swizzledMethod = class_getClassMethod([self class], @selector(canInitWithRequestS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getClassMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(canonicalRequestForRequest:));
Method swizzledMethod = class_getClassMethod([self class], @selector(canonicalRequestForRequestS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(startLoading));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(stopLoadingS));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didReceiveResponse:));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didReceiveResponseS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didReceiveData:));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didReceiveDataS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connectionDidFinishLoading:));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(connectionDidFinishLoadingS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
{
Method originalMethod = class_getInstanceMethod([NSClassFromString(@"PSDWebViewURLProtocol") class], @selector(connection:didFailWithError:));
Method swizzledMethod = class_getInstanceMethod([self class], @selector(connection:didFailWithErrorS:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
//
//
//
//
}
+ (BOOL)canInitWithRequestS:(NSMutableURLRequest *)request {
NSMutableURLRequest *mutableReq = [request mutableCopy];
NSMutableDictionary *headers = [mutableReq.allHTTPHeaderFields mutableCopy];
if ([headers[@"Key1"] isEqualToString:@"AAAA" ]){
return NO;
}
if([request .URL.description hasPrefix:@"http://"]){
// return YES;
}
NSLog(@"PSDWebViewURLProtocol canInitWithRequestS %@" ,request);;
return [self canInitWithRequestS:request];
}
//
//修改请求头 防止死循环
//
+ (NSURLRequest *)canonicalRequestForRequestS:(NSURLRequest *)request {
if([request .URL.description hasPrefix:@"http://"]){
// 修改了请求的头部信息
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[mutableRequest setValue:@"AAAA" forHTTPHeaderField:@"Key1"];
if ([mutableRequest allHTTPHeaderFields].count < 1) {
NSLog(@"空的空的");
}
NSLog(@"connection reset header");
return mutableRequest;
return request;
}else{
return [self canonicalRequestForRequestS:request];
}
}
//
//开始加载
//
- (void)startLoadingS{
NSMutableURLRequest *request = [self.request mutableCopy];
if([request .URL.description hasPrefix:@"http://"]){
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}else{
[self startLoadingS];
}
//替换为本地文件使用下面方法
// if ([request.URL.absoluteString containsString:@"hhhh"]) {
// NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL]
// statusCode:200
// HTTPVersion:@"1.1"
// headerFields:nil];
// //
// //如果是需要更改的页面则直接把数据返回给它 这个文件里的代码是通过第一次打印复制出来更改后的
// //
// NSString *myStr = [[NSBundle mainBundle]pathForResource:@"20190730_0.0.0.2" ofType:@"amr" inDirectory:nil];
// NSData *localdata = [[NSData alloc]initWithContentsOfFile:myStr];
// [[self client] URLProtocol:self
// didReceiveResponse:response
// cacheStoragePolicy:NSURLCacheStorageNotAllowed];
// [[self client] URLProtocol:self didLoadData:localdata];
// [[self client] URLProtocolDidFinishLoading:self];
// }
}
//
//取消请求
//
- (void)stopLoadingS {
[self stopLoadingS];
// [self.connection cancel];
}
//
//#pragma mark - NSURLConnectionDelegate
//
- (void)connection:(NSURLConnection *)connection didReceiveResponseS:(NSURLResponse *)response {
NSMutableURLRequest *request = [self.request mutableCopy];
if([request .URL.description hasPrefix:@"http://"]){
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
[self connection:connection didReceiveResponseS:response];
}
- (void)connection:(NSURLConnection *)connection didReceiveDataS:(NSData *)data {
NSMutableURLRequest *request = [self.request mutableCopy];
if([request .URL.description hasPrefix:@"http://"]){
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];;
if (str.length < 1) {
CFStringEncoding gbkEncoding =(unsigned int) CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
str =[[NSString alloc]initWithData:data encoding:gbkEncoding];
}
//
//打印h5的代码
//
NSLog(@"%@ %@",connection,str);
[self.client URLProtocol:self didLoadData:data];
}else{
return [self connection:connection didReceiveDataS:data];
}
}
- (void)connectionDidFinishLoadingS:(NSURLConnection *)connection {
NSMutableURLRequest *request = [self.request mutableCopy];
if([request .URL.description hasPrefix:@"http://"]){
[self.client URLProtocolDidFinishLoading:self];
}else{
[self connectionDidFinishLoadingS:connection];
}
//
}
- (void)connection:(NSURLConnection *)connection didFailWithErrorS:(NSError *)error {
NSMutableURLRequest *request = [self.request mutableCopy];
if([request .URL.description hasPrefix:@"http://"]){
[self.client URLProtocol:self didFailWithError:error];
}else{
[self connection:connection didFailWithErrorS:error];
}
}
@end
这些代码添加后能够走进来,对A功能的h5离线包也能正常打开。
但是对于一直白屏的B功能,还是白屏,而且要找的那个http请求没有走到这里。看来只能使用上面的方法解决。
重复上面的话:B功能的离线包正常打开,A功能的h5离线包白屏。
是不是想起来和客户端一点关系没有。
????????????????????????????????????????????????????????????????????????????????????????????????????????????????
学h5转h5去了。。。。。
客户端能做的也就这些了吧
上一篇: 一键离线下载python安装包: