一、场景
H5经常会需要选择手机照片来完善自身内容;比如上传身份证照片、资产照片等等等。有时候这些照片经常需要app处理完后才上传给H5,那么这时候作为app的你就必须先处理好H5选择的手机照片,再上传给他。所以本文接下来将讲解如何拦截处理H5选择的手机照片;
二、基础知识准备
普及基础知识:
H5选择手机照片的方式主要有两种:
- 1、通过与app的JS交互,选择手机照片;
- 2、通过H5自身的<input>标签,选择手机照片;
第一种JS交互的,图片数据的获取太容易处理了,就不再这里讲了。我们这边主要讲H5通过H5自身的<input>标签,选择手机照片。
三、拦截方法
这里我们先讲怎么实现,下一点再介绍思路。
实现方式很简单
1、添加已CJFileUploadPanel类
pod 'CJHook/CJFileUploadPanel'
CJFileUploadPanel类源码
2、建立DemoFileUploadPanel
类,使用CJFileUploadPanel
提供的接口实现你拦截后的图片处理。
DemoFileUploadPanel.h
#import <Foundation/Foundation.h>
@interface DemoFileUploadPanel : NSObject
+ (void)startHook;
+ (void)stopHook;
@end
DemoFileUploadPanel.m
#import "DemoFileUploadPanel.h"
#import <CJHook/CJFileUploadPanel.h>
#import "DemoCacheUtil.h"
@implementation DemoFileUploadPanel
+ (void)startHook {
__weak typeof(self)weakSelf = self;
[CJFileUploadPanel startHookWithAbsoluteFilePathHandle:^NSString *(UIImage *originImage) {
NSData *newImageData = [weakSelf dealImage:originImage];![分割图1.jpg](https://upload-images.jianshu.io/upload_images/6214155-49f701e7162b8ec8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
// 保存图片到本地
NSString *absoluteFilePath = [DemoCacheUtil saveImageData:newImageData forModuleType:DemoModuleTypeIot];
sleep(5); //用来测试是否主线程是否会被阻塞(请在选择图片后,选择返回,看是否卡住)
return absoluteFilePath;
}];
}
+ (void)stopHook {
[CJFileUploadPanel stopHook];
}
+ (NSData *)dealImage:(UIImage *)image {
UIImage *newImage = [UIImage imageNamed:@"饮品2.jpg"];
NSData *newImageData = UIImagePNGRepresentation(newImage);
return newImageData;
}
@end
3、调用
略。
如果你还想了解思路或者原理,请往下看,如果只是想使用的话,到这里就可以了。
四、拦截的思路分析
拦截的思路:1、拦截、替换系统方法;2、在新方法中按产品需求处理图片;
详细步骤如下。
1、拦截、替换系统方法
即:将在WKFileUploadPanel
中实现的UIImagePickerController
代理方法imagePickerController:didFinishPickingMediaWithInfo:
替换为你在其他类中写的其他方法。因为系统没提供WKFileUploadPanel
这个类给你来让你在该类中直接写交换的方法。
所以我们这里是将其替换为你在CJHookFileUploadPanel类中实现的- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
方法。
通过此步,你就能够在新写的方法- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
里面获取到图片选择器选取到的图片数据了。
@implementation CJHookFileUploadPanel
+ (void)hookFileUploadPanel:(BOOL)hook {
SEL originalSelector = @selector(imagePickerController:didFinishPickingMediaWithInfo:);
SEL swizzledSelector = @selector(swizzled_imagePickerController:didFinishPickingMediaWithInfo:);
Class originalClass = NSClassFromString(@"WKFileUploadPanel");
Class otherClass = [CJHookFileUploadPanel class];
if (hook) {
bool success = HookCJHelper_exchangeOriMethodToNewMethodWhichAddFromDiffClass(originalClass, originalSelector, otherClass, swizzledSelector);
NSLog(@"exchangeOriMethodToNewMethod:%@", success ? @"success": @"failure");
} else {
bool success = HookCJHelper_recoverOriMethodToNewMethodWhichAddFromDiffClass(originalClass, originalSelector, otherClass, swizzledSelector);
NSLog(@"recoverOriMethodToNewMethod:%@", success ? @"success": @"failure");
}
}
- (void)swizzled_imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
NSMutableDictionary *new_info = [[NSMutableDictionary alloc] initWithDictionary:info];
// 在这里按产品需求处理图片得到新new_info......
[self swizzled_imagePickerController:picker didFinishPickingMediaWithInfo:new_info];
}
@end
上述为某类添加另一个类中的方法的实现代码详见HookCJHelper
HookCJHelper源码
结束语
感谢阅读!