I've been trying to figure this one out for quite a while, and yet haven't found a solution.
Inside my app I'm extracting a website's HTML through an invisible WebView component. I do not need to view the website, just get the html it loads. The website uses JavaScript to load all of its content, and therefore I need a full web renderer in order to execute that JavaScript. In its current form, I'm overriding the WebViewClient's onPageFinished method to inject JavaScript that dumps the html into a JavaScriptInterface which then processes it.
My main issue here is that when I load this URL inside my app it would take about 8 seconds, whereas loading the exact same URL in the phone's chrome browser it takes less than a second. Any suggestions as to what might be the problem?
If it could be of any help, the JavaScript that gets executed stores a cookie inside the WebView, and then tries to retrieve it, and only if it finds said cookie (which has a short expiration time) it would load the site's HTML. In this case it actually loads data formatted with JSON (about 370k characters).
Relevant WebView code:
private void initWebView(View view) {
class JSInterface{
#JavascriptInterface
public void processHTML(String scheduleJSONResponse){
if(scheduleJSONResponse.length() > 10000){
Log.d(LOG_TAG, "Finished loading JSON");
}
}
}
webView = (WebView) view.findViewById(R.id.fragment_movies_web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JSInterface(), "Android");
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.d(LOG_TAG, "Page finished loading");
webView.loadUrl("javascript:window.Android.processHTML(document.getElementsByTagName('html')[0].textContent);");
}
});
webView.loadUrl(url);
}
As for why I check that the length is more than 10k characters: Sometimes onPageFinished would get called more than once, with the first call being before the JavaScript is executed, and so I get HTML containing the script to be executed which isn't what I need.
Thanks in advance for any help!
A logcat to demonstrate the issue:
08-18 22:32:23.623 26238-26238/com.michaelsvit.kolnoa I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#1e4dc08f time:502735009
08-18 22:32:23.638 26238-26238/com.michaelsvit.kolnoa W/cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 26238
08-18 22:32:31.336 26238-26238/com.michaelsvit.kolnoa D/MovieGridFragment: Page finished loading
Current code after simplifying it:
private void initWebView(View view) {
class JSInterface{
#JavascriptInterface
public void processHTML(String scheduleJSONResponse){
if(scheduleJSONResponse.length() > 10000){
Log.d(LOG_TAG, "Finished loading JSON");
}
}
}
webView = (WebView) view.findViewById(R.id.fragment_movies_web_view);
webView.getSettings().setJavaScriptEnabled(true);
//webView.addJavascriptInterface(new JSInterface(), "Android");
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.d(LOG_TAG, "Page finished loading");
//webView.loadUrl("javascript:window.Android.processHTML(document.getElementsByTagName('html')[0].textContent);");
}
});
}
through an invisible WebView component..
What when it is visible?
Try it!
Related
I'm trying to interact with my web view so I can get a value to later insert into a file (which is not important), When trying to execute the JavaScript I tried adding script tags and also removing the function which both ways don't work. I don't get any error in any way at all. How do I execute JavaScript in a loaded web view?
WebView myWebView = (WebView) findViewById(R.id.webload);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("https://www.example.co.uk");
myWebView.setWebViewClient(new WebViewClient());
myWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.evaluateJavascript("(function(){alert('e');})();", givenValue -> {
if (givenValue != null && !givenValue.isEmpty() && !givenValue.equals("null")) {
}
});
super.onPageFinished(view, url);
}
}
);
Hey i have worked used webview alot in my recent projects and the right way to execute the javascript in a loaded webpage is below.
webview.loadUrl("javascript:(function() {
// Your Javascript code , you can access dom elements and do whatever you want
})()");
Add this line in onPageFinished function of WebViewClient. also don't forget to enable javascript of your webview
I am unable to get some javascript to run successfully in the onPageFinished() method of my WebViewClient.
I am porting over an iOS app and they are doing the same thing, waiting for page to load, then using Javascript to hide some of the HTML items.
I don't use Javascript much but am not sure why it keeps failing to work correctly. Right now what happens is the page loads, then onPageFinished is called, and the page reloads and the text 'none' shows up in the top left corner.
I've attached my WebViewClient and then all the WebView setup I am doing in onCreate too. I have also included some commented out code of what I have tried before and that code also did not work.
// Manages the behavior when URLs are loaded
private class Browser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, headers);
return true;
}
#JavascriptInterface
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//view.loadUrl("javascript:document.getElementById('navbar_bg').style.display = 'none';");
//webView.loadUrl("javascript:document.getElementById(\"content\")");
view.loadUrl("javascript:document.getElementById(\"navbar_bg\").style.display=\"none\";");
}
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mobile_homework);
ButterKnife.bind(this);
homeworkId = getIntent().getIntExtra(HOMEWORK_ID_EXTRA, 0);
// Configure related browser settings
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
// Enable responsive layout
webView.getSettings().setUseWideViewPort(true);
// Zoom out if the content width is greater than the width of the viewport
webView.getSettings().setLoadWithOverviewMode(true);
//allow manual zoom and get rid of pinch to zoom
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
// Configure the client to use when opening URLs
webView.setWebViewClient(new Browser());
}
Edit: The final fix was to set variables to each change because it returns a variable when you change any item.
Final working code looked like:
view.loadUrl("javascript:var header = document.getElementById('header_bg_first').style.display='none'; " +
"var navbar = document.getElementById('navbar_bg').style.display='none'; " +
"var footer = document.getElementById('footer').style.display='none'; " +
"var iframePadding = document.getElementById('flcn_assignment').style.paddingRight='10px';");
I have two activity, one main activity(A) is an CordovaActivity, then I use intent to start another activity(B), in B i have an WebView(not CordovaActivity), and after I use this webview to load a simple webpage (alert something), I found the js code is not executed at all, even if I enable javascript by calling setttings.setJsenabel(true);
I start activity B from A
Load Url from webview in Activity B
simple web page
in the device, it does not alert anything
However, if I change the webview to CordovaWebView instead of the original Android native one, it works.....
That's because plain WebView doesn't support showing alerts by itself. You need to provide a WebChromeClient to it that implements WebChromeClient.onJsAlert method. For example:
mywebView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(
WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(view.getContext())
.setTitle("Alert")
.setMessage(message)
.setPositiveButton("Ok",
new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setCancelable(false).create().show();
return true;
}
});
I have occurred a problem. In my app,I load a url(a php page) by webview. It runs fun in many devices.But in a TV device,it offen exit without any error log.Now I know it is because the php page load a swf flash.But the page show well in the browser in the Tv.My code is as follows:
mWebView = (WebView) v.findViewById(R.id.shopWebView);
mWebView.setOnKeyListener(this);
mWebView.setInitialScale(100);
WebSettings webSet = mWebView.getSettings();
webSet.setJavaScriptEnabled(true);
webSet.setBlockNetworkImage(true);
webSet.setSupportZoom(true);
webSet.setBuiltInZoomControls(true);
webSet.setSupportMultipleWindows(true);
webSet.setUseWideViewPort(true);
webSet.setLoadWithOverviewMode(true);
// webSet.setPluginState(PluginState.ON);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.getSettings().setBlockNetworkImage(false);
}
});
mWebView.loadUrl(URL_SHOP);
Who can tell me what's wrong with my code or the reason of this case?(Forgive my poor English.)
Use WebChromeClient. That May help.
webView.setWebViewClient(new MyWebClient());
public class MyWebClient extends WebChromeClient {
}
I have solved this problem.I did like this:Before webview load url,I set the webview gone;and set webview visible in onPageFinished().Although I have solved the problem,but I don't know the exactly reason of that condition.If anyone know,please tell me.Is it because the TV's vedio memory or other things like that?
Is there any way to intercept javascript triggered URL in a WebView just like normal hrefs using shouldOverrideUrlLoading()?
onLoadResource() is called when any resource is being called, including JavaScript. The purpose is a bit different though than shouldOverrideUrlLoading().
webControls.setWebViewClient(new WebViewClient() {
//Notify the host application that the WebView will load
//the resource specified by the given url.
#Override
public void onLoadResource (WebView view, String url) {
super.onLoadResource(view, url);
Log.v(TAG, "onLoadResource("+url+");");
}
//Give the host application a chance to take over the
//control when a new url is about to be loaded in the
//current WebView.
#Override
public void shouldOverrideUrlLoading(WebView view, String url) {
super.shouldOverrideUrlLoading(view, url);
Log.v(TAG, "shouldOverrideUrlLoading("+url+");");
}
}