I am trying to make WebView display remote image (with certain stylistic tweaks). This works perfectly by loading WebView with an HTML snippet that references that remote IMG amongst other things. But the only problem is that sometimes this remote image is not present which results in a broken image icon.
What I would like to do is to intercept the (un)availability of the remote image and recover by switching to another one. I've tried using onReceivedError() of WebViewClient but somehow it does not trigger even when the image is not available.
My current image loading logic is as follows:
String url = "..."; // remote image URL
String html = String.format("<style>img{display: inline;" +
"height: auto;max-width: 100%%;}</style>" +
"<img src=\"%s\"></img>", url);
wv.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedError(WebView view, WebResourceRequest req,
WebResourceError rerr) {
Log.e("WEB_VIEW_TEST", "error code: " + errorCode);
}
});
wv.loadData(html, "text/html", null);
I suspect onReceivedError() only triggers for page-level errors and I'm not sure how to make it trigger for element-level errors. Any help would be very appreciated.
PS. While typing this, I've just thought about handling it in JS - that is, load webview with a JS snippet that tries to load the remote image and in case of an error loads another one - all within the JavaScript realm. I'll try it and if it works will post it here as well.
OK, the JavaScript solution works, although the question about intercepting in Android real still remains. Here's the JavaScript way:
String url = "..."; // real image
String backup_url = "..."; // backup image
WebView wv = (WebView) findViewById(R.id.fullImageWebView);
WebSettings webSettings = wv.getSettings();
webSettings.setJavaScriptEnabled(true);
// FIXME: put into assets as an HTML file
String template = "" +
"<style>\n" +
" img {\n" +
" display: inline;\n" +
" height: auto;\n" +
" max-width: 100%%;\n" +
" }\n" +
"</style>\n" +
"\n" +
"<img id='image'></img>\n" +
"\n" +
"<script>\n" +
" var second_attempt = false;\n" +
" var img = document.getElementById('image');\n" +
" img.src = '%s';\n" +
"\n" +
" window.addEventListener('error', function(e) {\n" +
" if (!second_attempt) {\n" +
" second_attempt = true;\n" +
" img.src = '%s';\n" +
" }\n" +
" }, true);\n" +
"</script>";
String html = String.format(template, url, backup_url);
wv.loadData(html, "text/html", null);
Related
I used this code and working but it first loads with website header and then afterward loads without header.
What is wrong in this code? What to modify so that only one screen loads, i.e, without website header?
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
webView.loadUrl("javascript:(function() { " +
"var head = document.getElementsByTagName('header')[0];"
+ "head.parentNode.removeChild(head);" +
"})()");
webView.loadUrl("javascript:(function() { " +
"var head = document.getElementsByTagName('footer')[0];"
+ "head.parentNode.removeChild(head);" +
"})()");
}
});
webView.loadUrl("https://www.google.com");
I resolved by putting this code in OnLoadResource() method instead of OnPageFinished() and using evaluateJavascript:
override fun onLoadResource(view: WebView?, url: String?) {
webView.evaluateJavascript("javascript:(function() { " +
"var head = document.getElementsByTagName('footer')[0];"
+ "head.parentNode.removeChild(head);" +
"})()", {});
}
Hello i am working on android application in which i want to play vimeo videos , i am getting response from Api in json and playing video using webview and it is playing good , but the webview is displaying very small and the playing video is also small my problems are
I want playing video width to be according to android device width. I can get it from Displaymetrics but how to set to iframe ?
I want to inflate custom view of media controller for playing videos.
Custom controller like play pause icon
I am getting this kind of url response from api
<iframe src="https://player.vimeo.com/video/video_id" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
at video_id i am getting the video id
Below is the code which i used
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND);
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
String data_html=getexplore_list.get(pos).getVideo_url();
webView.loadDataWithBaseURL("http://vimeo.com", data_html, "text/html", "UTF-8", null);
Please Provide any solution or link will be grateful
use style in html,
String url = "<iframe src=\"" + videoUrl + "\" style=\"border: 0; width: 100%; height: 95%; padding:0px; margin:0px\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>";
mViewHolder.webView.getSettings().setJavaScriptEnabled(true);
String yourData = "<div id='made-in-ny'></div>\n" +
"\n" +
"<script src='https://player.vimeo.com/api/player.js'></script>\n" +
"<script>\n" +
" var options = {\n" +
" id: 59777392,\n" +
" width: 540,\n" +
" loop: true\n" +
" };\n" +
"\n" +
" var player = new Vimeo.Player('made-in-ny', options);\n" +
"\n" +
" player.setVolume(0);\n" +
"\n" +
" player.on('play', function() {\n" +
" console.log('played the video!');\n" +
" });\n" +
"</script>";
mViewHolder.webView.loadData(yourData, "text/html; charset=utf-8", "UTF-8");
change id and width. it is working.
I am using an android WebView and I want to load webpage on my android device but display only some parts of webpage, not the whole page.
Is this possible?
I think what you want to do is remove some content from your HTML page and then display it in the WebView. This is possible via javascript so just before you display the page add some javascript code that will remove the elements you don't want.
LIKE
final WebView mWebView = (WebView) findViewById(R.id.mWebViewId);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
mWebView.loadUrl("javascript:(function() { " +
"document.getElementById('tableid')[0].style.display='none'; " +
"})()");
}
});
mWebView.loadUrl(youUrl);
Just replace document.getElementsByTagName('tableid') with document.getElementsByTagName('theElementYouWantToRemove') for every element and you're set. Original solution can be found at Display a part of the webpage on the webview android
for those who still looking for a solution:
WebView webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
mWebView.loadUrl("javascript:(function() { " +
"document.getElementsByClassName('className1')[0].remove();
document.getElementsByClassName('className2')[0].remove();
document.getElementsByClassName('className3')[0].remove();" +
"})()");
}
});
webView.loadUrl(url);
In Kotlin in this way:
view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
view.loadUrl(
"javascript:(function() { " +
"var head = document.getElementsByClassName('header')[0].style.display='true'; " +
"var head = document.getElementsByClassName('art-bnr')[0].style.display='none'; " +
"var head = document.getElementsByClassName('container-box')[0].style.display='none'; " +
"var head = document.getElementsByClassName('blog-sidebar')[0].style.display='none'; " +
"var head = document.getElementsByClassName('footer-container')[0].style.display='none'; " +
"})()"
) } }
view.loadUrl(url)
I'm working on an Android project with webview. Everything works fine but I can't set text to a textarea. I have a bunch of pages that have a memo-writing option. I'm loading the code for the memo to a page with jQuery:
$('#memoContainer').load("memo.html");
memo.html textarea:
<div class="sisalto">
<textarea id="memo" style="width: 100%"> </textarea>
</div>
The textarea works, I can write in it and I can get the contents and save it in Android with jQuery:
function save(){
var newContent = $('#memo').val();
AndroidFunction.saveFile(newContent);
}
I'm trying to get the saved contents and set it in the textarea:
var setMemo = $('#memo');
setMemo.innerText("DOESNT WORK");
setMemo.val('NOPE');
I've tried googling and browsing here for hours but can't seem to find anything useful. Many suggest the .val('smth'); option but it just doesn't work.
The memo is loaded before trying to set the content and everything is OK in my opinion. What is the problem here and any idea on how can I get this done?
Okay, the problem was the load-function. It loads the memo.html and shows it on the page but the actual code isn't injected to the page. Hence I can't set text to the textarea because it isn't actually there.
You should use a 'complete' function callback
$('#memoContainer').load('memo.html', function() {
var setMemo = $('#memo');
setMemo.val('hello');
});
Are you enabling javascript with the WebView? You need this to enable javascript:
WebView webView = ...
webView.getSettings().setJavaScriptEnabled(true);
Be sure jQuery is correctly loaded, can you post your code?
Here a working example (need internet permission since it uses CDN to load jquery):
import android.os.Bundle;
import android.app.Activity;
import android.webkit.WebView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String html = "<html>\n" +
"<body>\n" +
"<textarea id=\"area\"></textarea>\n" +
"\n" +
"<script src=\"http://code.jquery.com/jquery-1.10.0.min.js\"></script>\n" +
"<script src=\"http://code.jquery.com/jquery-migrate-1.2.1.min.js\"></script>\n" +
"\n" +
"<script type=\"text/javascript\">\n" +
" $(document).ready(function() {\n" +
" var area = $('#area');\n" +
" area.val('Hello');\n" +
" });\n" +
"</script>\n" +
"\n" +
"</body>\n" +
"</html>";
String mime = "text/html";
String encoding = "utf-8";
setContentView(R.layout.activity_main);
WebView web = (WebView) this.findViewById(R.id.web);
web.getSettings().setJavaScriptEnabled(true);
web.loadDataWithBaseURL(null, html, mime, encoding, null);
}
}
I am having a lot of trouble trying to play some youtube videos inside an Android Webview. I search everywhere but cannot find a solution that works.
I am using the following code:
WebView mWebView = (WebView) findViewById(R.id.webView1);
//Setup Webview
WebChromeClient client= new WebChromeClient();
mWebView.setWebChromeClient(client);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.getSettings().setSupportZoom(false);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.loadDataWithBaseURL("www.youtube.com", "<iframe class=\"youtube-player\" type=\"text/html\" width=\"640\" height=\"385\" src=\"http://www.youtube.com/embed/JEkbk-xDmZE?html5=1\" frameborder=\"0\">\n</iframe>", "text/html", "UTF-8", "");
The problem seems to be only with certain streams like this one: http://www.youtube.com/watch?v=JEkbk-xDmZE
The sound is great but the video is very slow, like 1 frame per second. unwatchable.
But if I use this stream: http://www.youtube.com/watch?v=GDFIYKmNw9Q
It works perfectly fine.
What is the difference between these live streams and how do I get the first one to play properly?
Also I should mention that sometimes the first one DOES play just fine. I am not able to figure out why it sometimes plays and other times doesn't. I've tried creating a new project with pretty much just a Webview and a Factory Reset device to eliminate any settings that may be effecting this but I still get the problem.
I've struggled with YouTube in general, trying to get it to work on android. Why certain videos lag is beyond me, but it might be different quality settings and limited bandwidth thus its buffering.
Hopefully one of the options below might help if it's not a buffering issue.
Currently, with WebView you use either use an IFrame or the YouTube API. Otherwise you can use the GData API to get the RSTP link to the video for use in a VideoView. Finally you can use an Intent to launch the YouTube app.
In the future there is a new API for Android for YouTube. But it has not been released. Theme again neither has Fragment support for Google Maps that was announced in Dec 2011. - http://www.youtube.com/watch?v=3WFsx-u-q3Y
Pros/Cons below (Examples are all making the WebView fill 100% of screen height and width)
WebView - IFrame - Limited configuration available. Runs in the WebView and works on nearly all platforms. Don't get me wrong, sometimes different options do not work, and you get a grey background when you try to play the video. Use the following site to create the IFrame code and try different options until it works for you - https://developers.google.com/youtube/youtube_player_demo (Do note several of the allowed configuration options do not work, such as hide controls has no effect). As mentioned there are lots of different options so trial and error is involved. Whilst several don't work, some look quite different. Looking at your question, i've never used the html5=1 option before, or set youtube.com as the base url.
webView = new WebView(this);
webView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
webView.getSettings().setPluginState(PluginState.ON);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webView.getSettings().setJavaScriptEnabled(true);
// Prevent scrolling of the webview
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setHorizontalScrollBarEnabled(false);
webView.setVerticalScrollBarEnabled(false);
webView.setWebChromeClient(new WebChromeClient()); //Blank webview to prevent null pointer plugin issues
webView.setWebViewClient(new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
});
String data = "<html>"+
"<head>"+
"</head>"+
"<body style=\"margin: 0; padding: 0\">"+
"<iframe " +
"type=\"text/html\" "+
"class=\"youtube-player\" "+
"width=\"100%25\" "+
"height=\"100%25\" "+
"src=\"http://www.youtube.com/v/" + uri +
"?controls=0&showinfo=0&showsearch=0&modestbranding=1&fs=0\" "+
"frameborder=\"0\"></iframe>" +
"</body>"+
"</html>";
webView.loadData(data, "text/html", "utf-8");
WebView - YouTube API - Much better, but requires flash. Therefore "Nexus 7" and any future devices released with JellyBean (4.1 and above) will not work. As the WebView on those devices uses a cut down version of Chrome rather than a cut down version of WebBrowser. Therefore as I found out yesterday, going forward this can't be used on our apps.
webView = new WebView(this);
webView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
webView.getSettings().setPluginState(PluginState.ON);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webView.getSettings().setJavaScriptEnabled(true);
// Prevent scrolling of the webview
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.setHorizontalScrollBarEnabled(false);
webView.setVerticalScrollBarEnabled(false);
webView.setWebChromeClient(new WebChromeClient()); //Blank webview to prevent null pointer plugin issues
webView.setWebViewClient(new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
});
String data = "<!DOCTYPE HTML>" + "<html>" + "<body style=\"margin: 0; padding: 0\">"
+ "<div id=\"player\"></div>"
+ "<script>"
+
// Load player api asynchronously.
"var tag = document.createElement('script');" + "tag.src = \"http://www.youtube.com/player_api\";"
+ "var firstScriptTag = document.getElementsByTagName('script')[0];" + "firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);"
+ "var done = false;" + "var player;" + "function onYouTubePlayerAPIReady() {" + "player = new YT.Player('player', {" + "height: '100%25',"
+ "width: '100%25'," + "videoId: '"
+ uri
+ "',"
+ "playerVars: { 'controls': "
+ controls
+ ", 'showinfo': 0, 'fs':0, 'modestbranding':1 },"
+ "events: {"
+ "'onReady': onPlayerReady," + "'onStateChange': onPlayerStateChange" + "}" + "});" + "}" + "function onPlayerReady(evt) {" +
// Autoplay
"evt.target.playVideo();" + "}" + "function onPlayerStateChange(evt) {" +
"}" + "function stopVideo() {" + "player.stopVideo();" + "}" + "</script>" + "</body>" + "</html>";
webView.loadData(data, "text/html", "utf-8");
VideoView - YouTube Data API - Can get access to information and importantly links to the video streams for use in a VideoView. The draw back is the free API is limited to low quaility 3GP videos not the MP4 (high quality/HD) streams. - https://developers.google.com/youtube/getting_started#data_api
Intent - Launch YouTube - Open the YouTube app with the video you want to play. Drawback is that another app is opened, thus not embedded into your app, and that some devices don't have YouTube installed.
if (AppChecker.isAppInstalled("com.google.android.youtube", this) == true)
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:" + uri));
startActivity(intent);
}
else
{
//Show youtube not installed
}
//Code to check if YouTube is installed.
public class AppChecker
{
public static boolean isAppInstalled(String uri, Activity activity)
{
PackageManager pm = activity.getApplicationContext().getPackageManager();
boolean app_installed = false;
try
{
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
}
catch (PackageManager.NameNotFoundException e)
{
app_installed = false;
}
return app_installed;
}
}