when I try the link in the browser, it opens very quickly
while on my Android webview, it runs slowly
what should i do so my webview can run faster?
webview.settings.javaScriptEnabled = true
val title = response.body()?.attachment
val filename = "http://lalala.com" + title
webview.loadUrl("http://docs.google.com/gview?embedded=true&url=" + filename)
webview.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH)
webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE)
if (Build.VERSION.SDK_INT >= 19) {
webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
else {
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webview.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
// do your stuff here
progressbar.visibility = View.GONE
webview.loadUrl("javascript:(function() { " +
"document.querySelector('[role=\"toolbar\"]').remove();})()")
}
}
Unofortunately, there won't be much you can do to fix this. However:
There's a couple of things you can try though, and a few things to check. Specifically:
You're setting the visibility to View.GONE (making your webview invisible) while the page is loading, and then making it visible again when the page has loaded. This is probably the problem.
Try without this, and you will probably find that it will be quicker. In my experience, onPageFinished(..) only fires some time after the page is loaded.
Does the page really require JavaScript ? If not, don't enable it.
If it's feaseable in your case, you can use a HTML parser like Jsoup to extract only the desired data from the page, and show that to the user. This will be a lot faster.
If the page uses Ajax to load data dynamically, you can also load the data directly from the endpoints it uses. Open the page in a desktop browser, and open the network tab of developer tools to find out how the page works and loads data.
You can block requests from the WebView with shouldInterceptRequest(..). This may help if the page has things like eg. Facebook share buttons or extra images which you don't need. Blocking these will speed up load times.
If you show us the URL you're using, maybe I can investigate more and tell you axactly how you could speed it up in your case. Let me know if it helps.
Related
I faced a problem, and hope somebody would be kind and give me a hand with it.
The problem is: I've got a webView in my application to open links on some news within my app (and I don't want to open them with browser or anything like that). And this news sometimes contains images.
When user tap on those images, they opens in the same size area as main news. And it looks quite bad.
[in picture bottom you can see top of the opened image][1]
[1]: https://i.stack.imgur.com/6M4fg.jpg
I already have a fragment in my structure to open images by url, but I don't know how to handle this "on-image" click in webView and grab image url from it to go to my ImageView fragment.
I read a bit about using javascript to take id from page html code, but there are no unique id's in html for those pictures.
You can provide your own WebViewClient and override shouldOverrideUrlLoading and then intercept click on a image.
Some example how it can looks like:
webView.webViewClient = object: WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
return if (isImage(request)) {
openImageViewFragment(request.url)
false // indicates that webview shouldn't do anything with the request
} else {
super.shouldOverrideUrlLoading(view, request)
}
}
}
There is a rather specific webpage loaded into WebView which URL is like http://www.site.com/mob/ (basically a mobile-optimized web page). This webpage display 25 articles only and on the bottom is a button "More articles".
When a user presses it, I catch URL http://www.site.com/Web/MobHomeItems.aspx?page=N (where N is 2, 3, 4...) and after that another 25 items have been loaded on the same screen.
Now, when I click on some article and go to article details, and later return to the page via the Back key, the WebView forgets how many articles have been loaded and simply loads the default page with 25 displayed articles. Imagine how frustrating this would be to a user if he came to 100th article.
I tried overriding many methods in WebClient and in WebChromeClient, but so far I have been unable to load N number of pages loaded via "More Articles" button. For example, I first thought this would help, but it did not.
#Override
public void onLoadResource(WebView view, String url) {
//http://www.site.com/Web/MobHomeItems.aspx?page=2
if (url.contains("?page=")) {
//save this URL for later and on return from
// article details, pass it to LoadResource()
super.onLoadResource(view, url);
}
Then I tried similar approach with other method - basically remembering how many pages have been loaded on the main page, and then on return from article details, simply tell webview to load this URL.
Can anyone help me? How to append loaded pages to the main page? Should I use JavaScript here maybe?
PS. Loading mentioned URL http://www.site.com/Web/MobHomeItems.aspx?page=N does not help as it loads this concrete page into the WebView only, and it does not append this Nth page to the main page.
EDIT
As #Raghunandan asked, I do not have problems loading back to 1st page (?page=1). This is default when user presses Back button on article details. I want to load to the page where a user was before pressing article details. If he was on ?page=100, I want to load back to that page e.g. I want to have 25x100 articles open. Again, default is always "open 25 articles or ?page=1 or http://www.site.com".
Override the method shouldOverrideUrlLoading of WebViewClient.
like this:
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (url is kind of article detail) {
WebView newOne = new WebView(); // create a new Webview for displaying the details.
view.setVisibility(View.INVISIBLE); // hiding current page (article list)
return true; // To tell the WebView we have process this url.
}
return false;
}
The user click one link of article's detail.
shouldOverriderUrlLoading would be triggered.
We created one new WebView to open the url.
Hiding current page
The user reading artical
The user click back key, close the newOne WebView then make the
previous WebView visible.The article list will show up immediately and remained the old statement
.
There is a another way to do this.
The WebSettings has a private method "setPageCacheCapacity" , the default value is 0 , you could enlarge it (may be 5).
You can access this method by using reflection of java.
The method can enable WebView to cache more than one document. In the other word. when user press the back key, the WebView will go back to the older document.
I have an app with a previously-existing, web-based registration process that I am trying to use inside a WebView. I need to add some style tags to the html in order to hide some elements for better displaying the content inside my app. I can get it to work on initial load, but I cannot figure out how to do it from one page to the next inside the WebView. Here is what I have working:
On initial load of the site, I am getting the raw html and appending "<style>MY STYLES HERE</style>" to the string before calling
wv.loadDataWithBaseURL(url, rawHtml, null, "UTF-8", url);
This works perfectly, but if a user clicks a link on the page and it loads another page into the WebView, then this code does not get called and the style tag is lost.
I assume I need to override "shouldOverrideUrlLoading" in the WebViewClient, but I don't know how to intercept the html from here. I thought I would try something like:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String rawHtml = getRawHtml(url) + "<style>...</style>";
wv.loadDataWithBaseURL(url, rawHtml, null, "UTF-8", url);
}
But this obviously sends it into an endless loop of intercepting the load to start a new load.
I have also tried overriding onPageFinished and doing:
wv.loadUrl("javascript:(function() { ... })()");
which works, except that it waits until the entire page is loaded before executing. This causes the page to appear loaded with all of the UI elements in tact, and then all of the ones I am trying to hide suddenly disappear. My ultimate goal is to enhance the look and feel of the site on a mobile device, so this is not an option.
Is there something else I can do in "shouldOverrideUrlLoading" to inject style tags? Or if not, what else can I try?
I've run into this problem, and depending on the number of redirects, etc, we have not been able to make the injected JavaScript available all the time.
At minimum, you should use the wv.loadUrl("javascript:(function() { ... })()"); approach, but call it in both onPageStarted() and onPageFinished().
Depending on the complexity of your pages, you might need to inject the JavaScript in onLoadResource() as well.
I am working on an android project right now and have a question about how to do callbacks in different webviews. I used JSInterface for my project too. Here I have 2 webviews. One has an index page, anther is a overlay(still a html page though.) What I want to do is if any user clicks on some links on the overlay, it should fire a callback function which is written in the java file where the index page was connected to through JSInterface. It might sound confusing, but I have draw something to help make it clear!
Thanks!
You can use a custom URL scheme like myurl://function for your functionality links. Then write an event handler for the WebView's shouldOverrideUrlLoading event in which you decide how to process the URL: either instruct the webview to load it, or do some custom action.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (url.startsWith("myurl://"))
{
// Parse further to extract function and do custom action
}
else
{
// Load the page via the webview
view.loadUrl(url);
}
return true;
}
I used startsWith to check the URL for this quick and dirty example, but you should consider using android.net.Uri.parse for parsing URLs.
This should allow you to call the Java function foo() without having to go through the first WebView.
If you want to go through the first webview, then you can call a function on the JSInterface like this (where webView1 is the first WebView retrieved through findViewById):
webView1.loadUrl("javascript:myjsinterface.myjsfunc();")
In my app, I am pulling down some HTML from a web service and displaying it in a WebView. Most of the time the app will display links in the HTML just fine, as in they are clickable and open up the Android Browser. Other times, however, the links are not clickable. It turns out sometimes the service will provide HTML with links that are not inside an href, and are just plain text.
Is there anyway for a WebView to parse the HTML and make these links "clickable"? I know the default Android Browser can do it, but I'm not sure about WebViews.
The Webview may not have built-in detectors to auto-link plain URLs within a page, but you could run a JavaScript function within the WebView to parse the URLs when the page finishes loading.
Basically, something like the following (I haven't checked this code for syntax yet, but it should give you the idea):
final WebView webview = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
webview.getSettings().setJavaScriptEnabled(true);
/* WebViewClient must be set BEFORE calling loadUrl! */
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
webview.loadUrl("javascript:(function() { " +
"var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig; " +
"document.getElementsByTagName('body')[0].innerHTML = document.getElementsByTagName('body')[0].innerHTML.replace(exp,'<a href='$1'>$1</a>');" +
"})()");
}
});
webview.loadUrl("http://code.google.com/android");
Note that the above JavaScript borrows the URL-parsing JavaScript regex from " How to replace plain URLs with links?," and more info can be found on JavaScript injection within the Android WebViewClient reference and at http://lexandera.com/2009/01/injecting-javascript-into-a-webview/ (not me).