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;
}
}
Related
While building a SNS hybrid application, I noticed that the webview gets scrolled nearly twice the distance than the actual gesture distance. This does not happen always, but I could not figure out the condition for this issue. The content of the webview gets extended as I scroll down, so I am suspecting that it is happening when I interact with the webview while the webview itself is loading and the content of the webview is getting extended. The below is the settings of my webview.
ps. once this issue occurs, it does not go away even if you navigate to another page.
iWebViewClient = new IWebViewClient(onActivity);
iWebChromeClient = new IWebChromeClient(onActivity, mContainer, webView, pbar);
webView.setWebViewClient(iWebViewClient);
webView.setWebChromeClient(iWebChromeClient);
webView.setVerticalScrollBarEnabled(false);
// javascript interface
webView.addJavascriptInterface(new WebViewInterface(onActivity), "ApplicationInterface");
WebSettings webSettings = webView.getSettings();
// enable javascript and storage
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // allow new window to open
webSettings.setSupportMultipleWindows(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
// enable css
WebView.setWebContentsDebuggingEnabled(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
// disable cache
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
// set useragent
String device = "Android " + Build.VERSION.RELEASE;
String appVersion = " " + BuildConfig.APPLICATION_ID + "/" + BuildConfig.VERSION_NAME;
String agentNew = webSettings.getUserAgentString() + appVersion + " (" + device + ")";
webSettings.setUserAgentString(agentNew);
if(initUrl != null){
webView.loadUrl(initUrl);
}else{
webView.loadUrl(HostUrls.webSite);
}
Turns out this only happens when my device is connected to chrome remote device inspection tool.
Once I connected my device to chrome inspection, the scroll speed doubled immediately and vice versa.
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);
i need to display another website into my android webview without it's header and footer
wb.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
wb.loadUrl("javascript:(function() { " +"document.getElementsByTagName('header')[0].style.display=\"none\"; " + "})()");
}
});
wb.loadUrl(url);
setContentView(wb);
Why not use iframe?
Try something like this -
String iframe = "<iframe scrolling=\"no\" src=\"YOUR URL\"" +
"width=\"400px\" height=\"300\"></iframe>";
webview.getSettings().setJavaScriptEnabled(true); //be sure to enable this or
//page might not load properly
webview.loadDataWithBaseURL("", iframe, "text/html", "UTF-8", "");
//loading iframe
You can customize the iframe code according to your needs. Be sure to add \ before every " in your HTML Code.
I'm using a WebView for displaying embedded Youtube video and that works on Galaxcy S2 (OS 2.3.5) and doesn't on Nexus S (OS 2.3.4), all I get is white screen without any video display.
Here is the code snippet I'm using and the declarations in Manifest file:
private WebView wv;
private void setWebView()
{
wv = (WebView) findViewById(R.id.webView);
wv.setWebChromeClient(new WebChromeClient());
wv.getSettings().setPluginState(WebSettings.PluginState.ON);
wv.setWebViewClient(new WebViewClient());
wv.getSettings();
wv.setBackgroundColor(0x00000000);
wv.setKeepScreenOn(true);
wv.setHorizontalScrollBarEnabled(false);
wv.setVerticalScrollBarEnabled(false);
wv.getSettings().setBuiltInZoomControls(true);
final String mimeType = "text/html";
final String encoding = "UTF-8";
String html = getHTML();
wv.loadDataWithBaseURL("", html, mimeType, encoding, "");
}
public String getHTML()
{
String html = "<html>"
+ "<head>"
+ "</head>"
+ "<body style=\"border: 0; padding: 0\">"
+ "<iframe "
+ "type=\"text/html\" "
+ "class=\"youtube-player\" "
+ "width= 100%\""
+ "\" "
+ "height= 95%\""
+ "\" "
+ "src=\"http://www.youtube.com/v/"
+ selected_video
+ "?controls=0&showinfo=0&showsearch=0&modestbranding=0" +
"&autoplay=1&fs=1&vq=hd720\" " + "frameborder=\"0\"></iframe>"
+ "</body>"
+ "</html>";
return html;
}
Note: the parameter "selected_video" is the hash of the video (VideoID).
The declarations in Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=http://schemas.android.com/apk/res/android
.
.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
.
.
android:hardwareAccelerated="true" >
.
.
Please let me know in case you recognizing anything I should change in my code, or help with a complete code which can support all Android devices and OS for displaying embedded (In-App) Youtube video with high quality.
UPDATE:
Pay attention, the solution I'm looking for should display high resolution video. I got it work on the different devices and OS using VideoView class but the video quality isn't good enough. So any solution including VideoView or WebView or any other way will be accepted only if it makes high quality YouTube video to be displayed. Thanks to all the responders!
there is an official YouTube Android Player API wich you can use. This is a bit more complicated but it is working better than other solutions using webclients.
First you must register your app in Googles API Console. This is completely free until your app gets over 25k request a month (or something like that). There are complete anf great tutorials under the link. I hope you can understand them. If not, ask! :)
How it looks:
Best solution to my case. I need video fit web view size.
Use embed youtube link with your video id.
Example:
WebView youtubeWebView; //todo find or bind web view
String myVideoYoutubeId = "-bvXmLR3Ozc";
outubeWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
WebSettings webSettings = youtubeWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);
youtubeWebView.loadUrl("https://www.youtube.com/embed/" + myVideoYoutubeId);
Web view xml code
<WebView
android:id="#+id/youtube_web_view"
android:layout_width="match_parent"
android:layout_height="200dp"/>
although I suggest to use youtube api or call new intent and make the system handle it (i.e. youtube app), here some code that can help you, it has a call to an hidden method because you can't pause and resume webview
import java.lang.reflect.Method;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.app.Activity;
#SuppressLint("SetJavaScriptEnabled")
public class MultimediaPlayer extends Activity
{
private WebView mWebView;
private boolean mIsPaused = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
String media_url = VIDEO_URL;
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebChromeClient(new WebChromeClient());
WebSettings ws = mWebView.getSettings();
ws.setBuiltInZoomControls(true);
ws.setJavaScriptEnabled(true);
mIsPaused = true;
resumeBrowser();
mWebView.loadUrl(media_url);
}
#Override
protected void onPause()
{
pauseBrowser();
super.onPause();
}
#Override
protected void onResume()
{
resumeBrowser();
super.onResume();
}
private void pauseBrowser()
{
if (!mIsPaused)
{
// pause flash and javascript etc
callHiddenWebViewMethod(mWebView, "onPause");
mWebView.pauseTimers();
mIsPaused = true;
}
}
private void resumeBrowser()
{
if (mIsPaused)
{
// resume flash and javascript etc
callHiddenWebViewMethod(mWebView, "onResume");
mWebView.resumeTimers();
mIsPaused = false;
}
}
private void callHiddenWebViewMethod(final WebView wv, final String name)
{
try
{
final Method method = WebView.class.getMethod(name);
method.invoke(mWebView);
} catch (final Exception e)
{}
}
}
It works like this:
String item = "http://www.youtube.com/embed/";
String ss = "your url";
ss = ss.substring(ss.indexOf("v=") + 2);
item += ss;
DisplayMetrics metrics = getResources().getDisplayMetrics();
int w1 = (int) (metrics.widthPixels / metrics.density), h1 = w1 * 3 / 5;
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebChromeClient(chromeClient);
wv.getSettings().setPluginsEnabled(true);
try {
wv.loadData(
"<html><body><iframe class=\"youtube-player\" type=\"text/html5\" width=\""
+ (w1 - 20)
+ "\" height=\""
+ h1
+ "\" src=\""
+ item
+ "\" frameborder=\"0\"\"allowfullscreen\"></iframe></body></html>",
"text/html5", "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
private WebChromeClient chromeClient = new WebChromeClient() {
#Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
FrameLayout frame = (FrameLayout) view;
if (frame.getFocusedChild() instanceof VideoView) {
VideoView video = (VideoView) frame.getFocusedChild();
frame.removeView(video);
video.start();
}
}
}
};
Embedding the YouTube player in Android is very simple & it hardly takes you 10 minutes,
1) Enable YouTube API from Google API console
2) Download YouTube player Jar file
3) Start using it in Your app
Here are the detailed steps http://www.feelzdroid.com/2017/01/embed-youtube-video-player-android-app-example.html.
Just refer it & if you face any problem, let me know, ill help you
The video quality depends upon the Connection speed using API
alternatively for other than API means without YouTube app you can follow this link
Refer to this answer: How can we play YouTube embeded code in an Android application using webview?
It uses WebViews and loads an iframe in it... and yes it works.
Pretty simple: Just put it inside a static method.
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(linkYouTube)));
Use this Youtube Embed API from google.
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);
}
}