-->

Change User Agent in UIWebView (iPhone SDK)

2018-12-31 22:04发布

问题:

I have a business need to be able to customize the UserAgent for an embedded UIWebView. (For instance, I\'d like the server to respond differently if, say, a user is using one version of the app versus another.)

Is it possible to customize the UserAgent in the existing iPhone SDK\'s UIWebView control the way it is, say, for an embedded IE browser in a Windows app?

回答1:

Modern Swift

Here\'s a suggestion for Swift 3+ projects from StackOverflow users PassKit and Kheldar:

UserDefaults.standard.register(defaults: [\"UserAgent\" : \"Custom Agent\"])

Source: https://stackoverflow.com/a/27330998/128579

Earlier Objective-C Answer

With iOS 5 changes, I recommend the following approach, originally from this StackOverflow question: UIWebView iOS5 changing user-agent as pointed out in an answer below. In comments on that page, it appears to work in 4.3 and earlier also.

Change the \"UserAgent\" default value by running this code once when your app starts:

NSDictionary *dictionary = @{@\"UserAgent\": @\"Your user agent\"};
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
[[NSUserDefaults standardUserDefaults] synchronize];

See previous edits on this post if you need methods that work in versions of iOS before 4.3/5.0. Note that because of the extensive edits, the following comments / other answers on this page may not make sense. This is a four year old question, after all. ;-)



回答2:

I had this problem too, and tried all methods. I found that only this method works (iOS 5.x): UIWebView iOS5 changing user-agent

The principle is to set the user agent permanently in the user settings. This works; Webview sends the given header. Just two lines of code:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@\"Mozilla/Whatever version 913.6.beta\", @\"UserAgent\", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

Setting User-Agent, or User_Agent in the mutable request, or overriding the setValue in the NSHttpRequest by swizzling, - I tried all that and controlled the results with wireshark, and none of that seems to work, because Webview still uses the user agent value from the user defaults, no matter what you try to set in the NSHttpRequest.



回答3:

It should work with an NSMutableURLRequest as Kuso has written.

NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: @\"http://www.google.com/\"]];
[urlRequest setValue: @\"iPhone\" forHTTPHeaderField: @\"User-Agent\"]; // Or any other User-Agent value.

You\'ll have to use NSURLConnection to get the responseData. Set the responseData to your UIWebView and the webView should render:

[webView loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL];


回答4:

Very simple in Swift. Just place the following into your App Delegate.

UserDefaults.standard.register(defaults: [\"UserAgent\" : \"Custom Agent\"])

If you want to append to the existing agent string then:

let userAgent = UIWebView().stringByEvaluatingJavaScript(from: \"navigator.userAgent\")! + \" Custom Agent\"
UserDefaults.standard.register(defaults: [\"UserAgent\" : userAgent])

Note: You may will need to uninstall and reinstall the App to avoid appending to the existing agent string.



回答5:

Actually adding any header field to the NSURLRequest argument in shouldStartLoadWithRequest seems to work, because the request responds to setValue:ForHTTPHeaderField - but it doesn\'t actually work - the request is sent out without the header.

So I used this workaround in shouldStartLoadWithRequest which just copies the given request to a new mutable request, and re-loads it. This does in fact modify the header which is sent out.

if ( [request valueForHTTPHeaderField:@\"MyUserAgent\"] == nil )
{
    NSMutableURLRequest *modRequest = [request mutableCopyWithZone:NULL];
    [modRequest setValue:@\"myagent\" forHTTPHeaderField:@\"MyUserAgent\"];
    [webViewArgument loadRequest:modRequest];
    return NO;
}

Unfortunately, this still doesn\'t allow overriding the user-agent http header, which is apparently overwritten by Apple. I guess for overriding it you would have to manage a NSURLConnection by yourself.



回答6:

Using @\"User_Agent\" simply causes a custom header to appear in the GET request.

User_agent: Foobar/1.0\\r\\n
User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7D11\\r\\n

The above is what appears in the dissected HTTP packet, essentially confirming what Sfjava was quoting from that forum. It\'s interesting to note that \"User-Agent\" gets turned into \"User_agent.\"



回答7:

Taking everything this is how it was solved for me:

- (void)viewDidLoad {
    NSURL *url = [NSURL URLWithString: @\"http://www.amazon.com\"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setValue:@\"Foobar/1.0\" forHTTPHeaderField:@\"User-Agent\"];
    [webView loadRequest:request];
}

Thanks Everyone.



回答8:

This solution seems to have been seen as a pretty clever way to do it

changing-the-headers-for-uiwebkit-http-requests

It uses Method Swizzling and you can learn more about it on the CocoaDev page

Give it a look !



回答9:

By pooling the answer by Louis St-Amour and the NSUserDefaults+UnRegisterDefaults category from this question/answer, you can use the following methods to start and stop user-agent spoofing at any time while your app is running:

#define kUserAgentKey @\"UserAgent\"

- (void)startSpoofingUserAgent:(NSString *)userAgent {
    [[NSUserDefaults standardUserDefaults] registerDefaults:@{ kUserAgentKey : userAgent }];
}

- (void)stopSpoofingUserAgent {
    [[NSUserDefaults standardUserDefaults] unregisterDefaultForKey:kUserAgentKey];
}


回答10:

I faced the same question. I want to add some info to the user-agent, also need to keep the original user-agent of webview. I solved it by using the code below:

    //get the original user-agent of webview
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
NSString *oldAgent = [webView stringByEvaluatingJavaScriptFromString:@\"navigator.userAgent\"];
NSLog(@\"old agent :%@\", oldAgent);

//add my info to the new agent
NSString *newAgent = [oldAgent stringByAppendingString:@\" Jiecao/2.4.7 ch_appstore\"];
NSLog(@\"new agent :%@\", newAgent);

//regist the new agent
NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:newAgent, @\"UserAgent\", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];

Use it before you instancing webview.



回答11:

Try this in the AppDelegate.m

+ (void)initialize 

{

    // Set user agent (the only problem is that we can’t modify the User-Agent later in the program)

    // iOS 5.1

    NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:@”Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3”, @”UserAgent”, nil];


    [[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];

}


回答12:

The only problem I have found was change user agent only

- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSDictionary *dictionary = [NSDictionary 
        dictionaryWithObjectsAndKeys:
        @\"Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5\", 
        @\"UserAgent\", nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
}


回答13:

To just add a custom content to the current UserAgent value, do the following:

1 - Get the user agent value from a NEW WEBVIEW

2 - Append the custom content to it

3 - Save the new value in a dictionary with the key UserAgent

4 - Save the dictionary in standardUserDefaults.

See the exemple below:

NSString *userAgentP1 = [[[UIWebView alloc] init] stringByEvaluatingJavaScriptFromString:@\"navigator.userAgent\"];
NSString *userAgentP2 = @\"My_custom_value\";
NSString *userAgent = [NSString stringWithFormat:@\"%@ %@\", userAgentP1, userAgentP2];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:userAgent, @\"UserAgent\", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];