iOS 攔截第三網頁下載應用

很多公司為了盈利,往往會在應用或網站中開放一些廣告位以實現盈利的目的,廣告鏈接內容往往是不可控,例如有些網頁頂部會有個提示條“下載APP”,這樣的問題在微信中他們也會攔截掉,那我們如何讓用戶點擊“下載APP”按鈕無法跳轉App Store中去下載呢?

一、網頁如何實現跳轉App Store

跳轉App Store協議:


(https)|(itms-apps)://itunes.apple.com/app/id{appID}

js應用:

下面方法最終也會轉為itms-appss://協議


window.location.;

或者直接使用應用跳轉協議

window.location.href = "itms-apps://itunes.apple.com/app/id{appID}";

iOS 實現跳轉:

itms-apps://協議是不能直接跳轉的,需要借助openURL:方法才能跳轉到應用商店,我們在下面方法可以實現跳轉App Store、撥打電話、調用第三方應用等功能


- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURLRequest *request = navigationAction.request;
    NSString *scheme = [request.URL scheme];
    
    if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        
        [[UIApplication sharedApplication] openURL:request.URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:^(BOOL success) {
        }];
        
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

二、如何攔截

都知道它是怎么跳轉的,攔截感覺很簡單了

方法一

不實現- (void)webView:decidePolicyForNavigationAction:decisionHandler:代理方法

方法二


- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURLRequest *request = navigationAction.request;
    NSString *scheme = [request.URL scheme];
    
    if (![scheme isEqualToString:@"https"] && ![scheme isEqualToString:@"http"]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        
        if ([scheme hasPrefix:@"itms-apps://"] || [scheme hasPrefix:@"itms-appss://"]) return;

        [[UIApplication sharedApplication] openURL:request.URL options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:^(BOOL success) {
        }];
        
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

上面這種做法會攔截所有的跳轉App Store請求,但是我們想要某些可以跳轉,這個時候我們需要一個白名單,如果appId在跳轉白名單內就可以跳轉。

方法三

有的時候我們能會有多個WebView來展示網頁,在每個網頁處理起來就會有很多重復的代碼。另外一種方法就是使用MethodSizzling來實現攔截

#import "UIApplication+OpenUrlBlock.h"

@implementation UIApplication (OpenUrlBlock)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originalSelector = @selector(openURL:options:completionHandler:);
        SEL swizzledSelector = @selector(swiz_openURL:options:completionHandler:);
        [self swizzlingInClass:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
        
        SEL originalSelector2 = @selector(openURL:);
        SEL swizzledSelector2 = @selector(swiz_openURL:);
        [self swizzlingInClass:[self class] originalSelector:originalSelector2 swizzledSelector:swizzledSelector2];
    });
}

+ (void)swizzlingInClass:(Class)cls originalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
    Class class = cls;
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, 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);
    }
}

- (void)swiz_openURL:(NSURL*)url options:(NSDictionary<UIApplicationOpenExternalURLOptionsKey, id> *)options completionHandler:(void (^)(BOOL success))completion {
    NSLog(@"調用openURL:options:completionHandler方法打開:%@", url.absoluteString);
    NSURL *filtrateUrl = [self filtrateDowloadWithUrl:url];
    [self swiz_openURL:filtrateUrl options:options completionHandler:completion];
}

- (BOOL)swiz_openURL:(NSURL*)url {
    NSLog(@"調用openURL方法打開:%@", url.absoluteString);
    NSURL *filtrateUrl = [self filtrateDowloadWithUrl:url];
    return [self swiz_openURL:filtrateUrl];
}

// 過濾非白名單應用,不讓去跳轉下載
- (NSURL *)filtrateDowloadWithUrl:(NSURL *)url {
    NSURL *filtrateUrl = url;
    if ([url.absoluteString hasPrefix:@"itms-apps://"] || [url.absoluteString hasPrefix:@"itms-appss://"]) {
        if (![self isAppDowloadWithUrl:url]) {
            filtrateUrl = [NSURL URLWithString:@""];
        }
    }
    return filtrateUrl;
}

// 攔截openUrl判斷應用是否可以下載
- (BOOL)isAppDowloadWithUrl:(NSURL *)url {
    NSArray *whiteList = [self appDowloadWhiteList];
    __block BOOL isAppDowload = NO;
    [whiteList enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
        NSString *appId = obj[@"appId"];
        if ([url.absoluteString containsString:appId]) {
            isAppDowload = YES;
            *stop = YES;
            return;
        }
    }];
    return isAppDowload;
}

- (NSArray *)appDowloadWhiteList {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"AppDowload" ofType:@"plist"];
    NSArray *ary = [NSArray arrayWithContentsOfFile:filePath];
    return ary;
}

@end

應用白名單plist文件


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>appName</key>
        <string>應用名稱</string>
        <key>appId</key>
        <string>應用id</string>
    </dict>
</array>
</plist>

總結

  • 如果提供給外部網頁加載WebView很少,還是建議使用第二種在代理方法內攔截
  • 使用MethodSizzling雖然在WebView中不用寫任何代碼,但是同樣存在出現問題難排查情況
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容