How do you change the user agent used by WKWebview?
With the older WebView, I could write the following to change the user agent:
[myWebView setCustomUserAgent:#"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4)
AppleWebKit/537.77.4 (KHTML,like Gecko) Version/7.0.5 Safari/537.77.4"];
Very simple in Swift. Just place the following into your App DelegatedidFinishLaunchingWithOptions.
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent" : "Custom Agent"])
If you want to append to the existing agent string then:
let userAgent = UIWebView().stringByEvaluatingJavaScriptFromString("navigator.userAgent")! + " Custom Agent"
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent" : userAgent])
Note: You will need to uninstall and reinstall the App to avoid appending to the existing agent string.
I don't have an answer for this. However, some pointers from my research so far:
In iOS, it's possible to set a custom user agent for a UIWebView like this:
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:agent, #"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
In OSX, there was a setCustomUserAgent method for WebView elements that did the trick.
However, this doesn't work for WKWebView (at least, in OSX). I couldn't find any documentation about it from Apple, either.
Hope somebody can help!
I ran into the same issue, but managed to work around it using a combination of loadHTMLString on the WKWebView and a NSMutableURLRequest to do the heavy lifting.
My search on how to call some method on the WKWebView itself lead me to http://trac.webkit.org/changeset/165594, which implies there is a private method _setCustomUserAgent to do this. I'm not proficient enough in cocoa/swift to figure this one out.
I ended up using the code below, as I really only need to fetch the contents of a single URL and display it, but it may be helpful in some way.
What it does is simply loading the contents of an URL into the WKWebView as string, I suspect you may lose back/forward navigation and such, and it will only work for the initial page display, as the WKWebView will take over clicks and asset loading.
(please note, this example is written in Swift and not Objective-C)
self.webView = WKWebView(frame: webViewRect, configuration: webViewConfig)
// create the request
let url = NSURL(string: "https://example.com/")
let request = NSMutableURLRequest(URL: url!)
request.setValue("YourUserAgent/1.0", forHTTPHeaderField: "User-Agent")
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
let content = NSString(data: data, encoding: NSUTF8StringEncoding)
self.webView!.loadHTMLString(content!, baseURL: url)
}
It wouldn't be ideal but you could likely implement a custom NSURLProtocol handler to intercept HTTP requests and modify them with your custom user-agent header. I don't think this would work on iOS since WKWebView makes requests out-of-process and bypasses any registered NSURLProtocols. But it might work on OS X?
With a user entered URL in a text field, you can completely control the NSURLRequest using an NSMutableURLRequest object, and set the header field for it.
However, with things the user actually clicks on within the web view, you're kind of not in control from obvious and clearly documented Objective-C land.
I do not see any documented way beyond what WKWebView seems to push things toward, JavaScript. So, that means you can do things like posted here:
Mocking a useragent in javascript?
Using the script injection APIs.
This is why I do not like WKWebView. I want to like it, but I do not want to learn to do half of everything in JavaScript.
So, you can create a WKUserScript object to do this, and set its injection time to WKUserScriptInjectionTimeAtDocumentStart. That will enable you to handle things requested from page elements within the document, as long as the page itself is not loading other scripts that conflict.
First Quit Safari. Then open Terminal and paste this command, and press enter:
defaults write com.apple.Safari CustomUserAgent "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/538.46 (KHTML, like Gecko) Version/7.1 Safari/537.85.7\""
Open Safari and you're done.
To undo this change, close Safari and paste this command into terminal:
defaults delete com.apple.Safari CustomUserAgent
Sometimes a restart may be required to get these changes to stick, not sure why, could be a cache thing.
I'm developing a Cordova 2.9.0 app for Windows Phone 8. The app in question utilises external content heavily, using the JS and HTML content that's being served from another source. It all works fine, but the browser component caches heavily.
The only way I have discovered to clear caches is to uninstall-install the app again to take effect. The downside to this is that my localStorage also clears, slowing down my cycles.
I presume the cache can be cleared by writing extra C# into the Cordova template they serve, which I use by the way.
So while it was not that critical, I did stumble to a working answer. The WebBrowser class does have a suitable method to call: ClearInternetCacheAsync.
Since CordovaBrowser inherits from WebBrowser, it's just a matter of adding one line to MainPage.xaml.cs where the C# init of the start page happens:
namespace FooBarApp
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
this.CordovaView.Loaded += CordovaView_Loaded;
// blammo!
this.CordovaView.CordovaBrowser.ClearInternetCacheAsync();
}
Phonegap Cookies Plugin can be found HERE
A simple, lightweight jQuery plugin for reading, writing and deleting cookies can be found HERE
I hope it will resolve your problem. Thanks!!
I am trying all means to improve the loading time of an link in android webview in vain.I am using a link which has images and text fetched from external server by using some js functions and those images and text may change on any moment.In this scenario the code I used is as below.I am not interested in HTML 5 caching or server caching techniques,as the same link loads faster on browser fails to do the same in android webview.There is not much js script i can load from resource to improve performance hence most of the script just pulls data from external server and images from on amazon server.
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
settings.setPluginState(PluginState.ON);
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
settings.setDomStorageEnabled(false);
settings.setLoadsImagesAutomatically(true);
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
settings.setJavaScriptEnabled(true);
settings.setAppCacheEnabled(false);
settings.setGeolocationEnabled(false);
1 .I guess turning on DomStaorage and AppCache to true have impact on loading time so i have turned it off. -> Is this true
2.In OnDestroy i call clearcache on webview to clear application cache - I am doing this hence i am afraid that my app size may grow as webview db grows if i fail to clear.-> is this must,or android handles this gracefully.
3.Few suggestion i hear is to set setCacheMode to LOAD_NO_CACHE and comment clearing webview cache in onDestroy. --> Does calling webview.clearcache() have any impact hence I have already set not to load from cache.
4.The link does not provide me information of previously refreshed time,in that case what cache mode could any one recommend.
5.Is there is any concert testing method to find out loading time on devices that takes network connection and server lags into account.hence the same page once it loads fast may load slow in some other time.
Give a try with "fast click".
mobile browsers will wait approximately 300ms from the time that you tap the button to fire the click event. The reason for this is that the browser is waiting to see if you are actually performing a double tap.
Download the script, add
<script type='application/javascript' src='fastclick.js'></script>
in your header and this code in your script.
window.addEventListener('load', function() {
FastClick.attach(document.body);
}, false);
More informations: https://developers.google.com/mobile/articles/fast_buttons
I am using the WebView component and sometimes I reload this component. But sometimes, before reloading I would like to get the URL where the WebView is still pointing.
Is it possible to get this information??
Thank you in advance.
Alex
UIWebView *myWebView = // ... well, we'll just say it exists.
NSLog(#"last loaded or currently loading URL: %#", myWebView.request.URL);
The request is a NSURLRequest object which was used to request the page so you can pretty much get anything might need out of it.
I load HTML file which loads images using Javascript files to WebView. Every time when I load html file to Web view it shows me some memory increased in Activity Monitor. Even, when I release Webview then also it does not release the memory.
I am not caching the resources in Webview. But, when I used instruments to analyse the memory , it shows me images resources are cached in memory which does not get released.
I tried to load same HTML files in Safari browser, I found the same behavior.
Can anyone please guide me where I am missing? How can I optimize the memory loading to WebView?
Do not use Activity Monitor for profiling memory performance in your app.
Use the Instruments app and the various memory-related tools it provides, such as Allocations and Leaks. You will then be able to determine if your app is truly leaking.
More inputs how I try to avoid caching in WebView.
I am using below piece of code to remove caching.
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
WebPreferences *the_pPrefs = [m_pWebView preferences];
[the_pPrefs setCacheModel:WebCacheModelDocumentViewer];
[the_pPrefs setUsesPageCache:NO];
[m_pWebView setResourceLoadDelegate:self];
Even I handle resource load request in below delegate method.
- (NSURLRequest *)webView:(WebView *)sender
resource:(id)identifier
willSendRequest:(NSURLRequest *)aRequest
redirectResponse:(NSURLResponse *)redirectResponse
fromDataSource:(WebDataSource *)dataSource
{
NSURL * url = [aRequest URL];
NSURLRequest * cachelessRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:100];
return cachelessRequest;
}
I hope I doing the right things to avoid caching. Please give your thoughts for the same.