在工作中发现,有些app本身没有实现推送功能。
而我们在没有源码的情况下,想给这些app发送推送消息。
这个时候,我们就需要通过注入来给App实现相关功能。
网上很多注入都是通过Tweak实现的。 我这里通过纯手写的方式实现推送注入。
1,首先我们需要hook住AppDelegate内的推送相关方法。
示例代码:
+(void)load{
Class oriMethodClass1 = NSClassFromString(@"AppDelegate");
swizzleMethod(oriMethodClass,[self class], @selector(application:didFinishLaunchingWithOptions:), @selector(sw_application:didFinishLaunchingWithOptions:));
swizzleMethod(oriMethodClass,[self class], @selector(userNotificationCenter:willPresentNotification:withCompletionHandler:), @selector(sw_userNotificationCenter:willPresentNotification:withCompletionHandler:));
swizzleMethod(oriMethodClass,[self class], @selector(application:didFailToRegisterForRemoteNotificationsWithError:), @selector(sw_application:didFailToRegisterForRemoteNotificationsWithError:));
swizzleMethod(oriMethodClass,[self class], @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:), @selector(sw_application:didRegisterForRemoteNotificationsWithDeviceToken:));
}
void swizzleMethod(Class class,Class class1, SEL originalSelector,SEL swizzledSelector)
{
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class1, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod)
{
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
然后在自己的类里面实现相关的函数:
- (BOOL)sw_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 必须写代理,不然无法监听通知的接收与点击
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 点击允许
NSLog(@"apns注册成功");
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@", settings);
}];
} else {
// 点击不允许
NSLog(@"apns注册失败");
}
}];
}else if ([[UIDevice currentDevice].systemVersion floatValue] >8.0){
//iOS8 - iOS10
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]];
}else if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {
//iOS8系统以下
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
}
// 注册获得device Token
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
- (void)sw_application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSMutableString *deviceTokenString = [NSMutableString string];
}
// 注册deviceToken失败
- (void)sw_application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"error -- %@",error);
}
- (void)sw_userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
// 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
completionHandler(UNNotificationPresentationOptionBadge|
UNNotificationPresentationOptionSound|
UNNotificationPresentationOptionAlert);
}
这样,我们打包一个dylib 注入到应用就能给应用实现推送功能了。
但是,你会发现一个问题。有的App 他的delegate名称并不叫AppDelegate。这样我们就无法hook到相关方法。
别着急。
我们可以通过hook UIApplication 的 setDelegate来获得当前delegate的类名:
示例如下:
Class oriMethodClass1 = NSClassFromString(@"UIApplication");
swizzleMethod(oriMethodClass1,oriMethodClass1, @selector(setDelegate:), @selector(TY_setDelegate:));
通过delegate.class 即可获得类名。这样就能实现一个通用的推送注入包。
以上,如有问题可联系我。 欢迎指正!