Android Webview "Sandboxing is not allowed" when loading iframe stream - java

I am attempting to load another site's iframe into my android app via webview. I am able to properly load other websites but when I load a stream from sportsbay.org which provides you with an iframe embed code snippet, the stream goes black and it prints "Sandboxing is not allowed". I have gone through several other questions to find an answer to this. My android project is as follows.
The specific url that I am passing in as video_url is https://sportsbay.org/embed/45629/1/btn-big-ten-network-live.html. The iframe snippet that sportsbay provides is <iframe allow='encrypted-media' width='640' height='360' marginwidth='0' marginheight='0' scrolling='no' frameborder='0' allowfullscreen='yes' src='//sportsbay.org/embed/45629/1/btn-big-ten-network-live.html'></iframe>. This url loads two urls 1) https://lowend.xyz/stream/45629.html which is the actual stream and moments later loads 2) https://sportsbay.org/live-streams to redirect you to the home page of sportsbay. I have code in MyWebViewClient that prevents the main sportsbay page from loading which would interrupt the stream I want to play (THIS is where I get the sandboxing message). I have tried replacing loadUrl with loadData and other variations that pass in the iframe html string along with the mimeType but what I have currently is the closest I have come to loading the stream (others don't get far enough to post the sandboxing message).
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Bring Linear layout into view.
setContentView(R.layout.webview);
// Grab current intent & pull out video url.
Intent i = getIntent();
String video_url = i.getStringExtra("video_url");
// Removes app name banner at top. Allows for orientation changes without reload.
getSupportActionBar().hide();
// Creates webview object.
WebView web = findViewById(R.id.webView);
// Configure settings for webview.
WebSettings webSettings = web.getSettings();
// Allows use of the phones file storage.
webSettings.setDomStorageEnabled(true);
// Sets encoding standard for urls.
webSettings.setDefaultTextEncodingName("utf-8");
// Able to zoom.
webSettings.setSupportZoom(true);
// Needed for websites to load javascript enabled content (most videos/streams).
webSettings.setJavaScriptEnabled(true);
// Attached webview to java class MyWebViewClient that vets the incoming urls before loading.
// Blocks Ads / viruses / popups.
// Also keeps url from launch in a browser.
web.setWebViewClient(new MyWebViewClient());
// Checks if channel is sourced from sportsbay.org.
if(video_url.contains("sportsbay.org"))
{
// Changes the browser user agent since chrome user agent returns 403 Forbidden message.
webSettings.setUserAgentString("Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion");
}
web.loadUrl(video_url);
}
public class MyWebViewClient extends WebViewClient {
public boolean shouldOverrideKeyEvent (WebView view, KeyEvent event) {
return true;
}
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
final Uri uri = Uri.parse(url);
return handleUri(uri);
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
final Uri uri = request.getUrl();
return handleUri(uri);
}
private boolean handleUri(final Uri uri) {
Log.i(TAG, "Uri =" + uri);
final String host = uri.getHost();
final String scheme = uri.getScheme();
// Check requested URL to known good
if (host.equals("s1-tv.blogspot.com") ||
host.equals("reddit-tv-streams.blogspot.com") ||
host.equals("newdmn.icu") ||
host.equals("lowend.xyz"))
{
// Returning false means that you are going to load this url in the webView itself
return false;
} else {
// Do not load the requested URL
return true;
}
}
}

Great news! I figured it out. The sandboxing message was not because of the server incorrectly interacting with my app, it was because my app did not have permission to use the file storage outside of the android application (the app sandbox). This was fixed with:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
which needs to be placed in the Android Manifest.xml in the permissions area (under the top package).

Related

Change URL while loading it in browser - Android Studio

I have created an app that will load links from my server into the webview. However, I have also written an intent to open the link in the user's browser so they can download the file. I want the link to change a bit while it loads in the browser.
I.e:
This is the link : https://www.example/v/file
My app should change "v" to "f" and load in the user's browser.
Like this: https://www.example/f/file
My code:
private void initWebDowload(String s){
webView.loadUrl(s);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(s));
startActivity(i);
}
Kinda complicated but you need to attach a custom WebViewClient to your WebView so you can change the URL loading behaviour.
Just to give an example:
webView.setWebViewClient(new CustomWebViewClient());
private class CustomWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// right here you are given the chance to change the [url] ^
view.loadUrl(url.replace("/v/file", "/f/file")); // replace v with f
return true;
}
}
}

Android webview mulitple windows. How to detect is created window from html target="blank" or from javascript?

Android webview mulitple windows. How to detect is created window from html target="blank" or it is a javascript popup?
I have next code in own browser:
WebSettings settings = webView.getSettings();
settings.setDomStorageEnabled(true);
settings.setJavaScriptEnabled(true);
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
settings.setGeolocationEnabled(true);
settings.setSupportMultipleWindows(true);
also implementation create new windows in our ChromeClient:
#Override
public void onCreateWindow(WebView webView, boolean isDialog, boolean isUserGesture, Message resultMsg) { //logic for create new webview and set new url in it. }
We want to warn user about created new tab, but only if popup get from javascript code, because it is usually ad, and also many non ad pages use target="blank" attribute from html.
Okay. First you can try do something by adding custom WebChromeClient. Methods
onJsBeforeUnload(WebView view, String url, String message, JsResult result)
onJsConfirm(WebView view, String url, String message, JsResult result)
Also, ou can try by changing WebSettings of your WebView.
https://developer.android.com/reference/android/webkit/WebSettings.html
I found this. setJavaScriptCanOpenWindowsAutomatically(boolean flag)
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView.HitTestResult result = view.getHitTestResult();
int type = result.getType();
if (type == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
}
in if case we can handle action from html only, else different cases: auth2.0, or window.open("http://test.ua")

Android WebView getFavicon() returning null

I'm trying to get the favicon of the loaded page after using
WebView webView = new WebView(getActivity());
webView.loadUrl("http://" + url);
I'm attaching the asynchronous WebViewClient to the WebView to get the favicon after it loads
webView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
String linkTitle = view.getTitle();
Bitmap favicon = view.getFavicon();
onLinkUrlFinished(url, linkTitle);
}
});
The favicon getting back is always null, even for websites such as google/facebook that has favicons for sure.
Another thread says to use WebIconDatabase but it's deprecated:
Display the Android WebView's favicon
The API on android site refers to WebViewClient.onReceivedIcon which doesnt even exist.http://developer.android.com/reference/android/webkit/WebView.html#getFavicon%28%29
What's going on here?
In order to use onReceiveIcon(), you should use setWebChromeClient.
This is what I do and it's working for me.
webView.setWebChromeClient(new WebChromeClient() {
#Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
progressBar.setProgress(newProgress);
}
#Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
webImage.setImageBitmap(icon);
}
});
WebIconDatabase is deprecated as of API 19. According to the comments in the code:
#deprecated This class is only required when running on devices up to
{#link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}
So unless you don't want to support API 18 and below, you should still be using WebIconDatabase:
WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath());
And then, regardless what API you want to support, you need to specify in a custom WebChromeClient:
public class MyCustomWebChromeClient extends WebChromeClient {
#Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
// do whatever with the arguments passed in
}
}
Remember to register your custom WebChromeClient with your WebView:
mWebView.setWebChromeClient(new MyCustomWebChromeClient());
The key is to open the WebIconDatabase so WebView has somewhere to put the icons, and override WebChromeClient.onReceivedIcon. For additional information, see this StackOverflow article.
I know its an old thread but, for those facing problems getting favicon using webview client.
Kotlin:
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
tabTitle.text = view?.title // read website title
loadImg(view) // method to load the favicon
}
private fun loadImg (view: WebView?){
// u can directly use tabImage.setBitmap instead of assigning tabImg as val
val tabImg: ImageView = findViewById(R.id.tabImage)
// creating handler object to delay the associated thread a little bit after onPageFinished is called.
val handler = Handler()
val runnable = Runnable {
if(view?.favicon != null) {
tabImg.setImageResource(0) //remove the default image
tabImg.setImageBitmap(view?.favicon) // set the favicon
}
}
handler.postDelayed(runnable, 200) // delay time 200 ms
}
It worked for me, hope it helps new readers, plz up vote if it helps u, so that u can help others!
Best regards
So in the end I didn't end up using the deprecated API, instead I found out that if you put /favicon.ico after the domain, it'll give you the ico file, which I used in the end to fetch the image. The Uri API will have a getHost() method that will give you the host without having to manually parse it
String faviconUrl = Uri.parse(url).getHost() + "/favicon.ico";
For google for example the icon url will be www.google.com/favicon.ico

Opening a page in Webview by passing URL parameters

I am working on an Android Application that opens an HTML page in a webview within the app. The HTML page is stored in the assets folder and I call it by means of
loadUrl("file:///android_asset/a.html");
Now, the page is such that it accepts parameters from the URL (javascript). I need to know how do we pass URL parameters to this html file that is stored inside the assets folder. Writing them like this:
loadUrl("file:///android_asset/a.html?q=2&w=3");
doesn't work.
Is there any other way?
Riya
If your HTML page handles the parameters via javascript (and i can't think of any other way it can handle them), you can call a javascript function in your code with the parameters after the page is loaded, and pass parameters to it.
webview.getSettings().setJavaScriptEnabled(true);  
webview.setWebViewClient(new WebViewClient() {  
#Override  
public void onPageFinished(WebView view, String url)  {  
webview.loadUrl("javascript:(function() { setParameters(2,3)})()");  
}
});
webview.loadUrl("file:///android_asset/a.html");  
I tried the method suggested by shaish and many others for passing url parameters to an 'asset folder' url. It seems that this is a well known bug for android 3 and 4 (http://code.google.com/p/android/issues/detail?id=17535). Simply calling webview.loadUrl("file:///android_asset/a.html?q=2&w=3") works on a blackberry 10 simulator.
A similar explanation like shaish but adapted to my own case:
My problem was that anytime I switched to another app, when coming to the webapp, the webview kept reloading. I guess that's because of the following line in my onCreate() method: myWebView.loadUrl(url); I had the idea to pass these state variables in the url, but as you know it is not possible yet.
What I did was to save the state of some variables using onSaveInstanceState(Bundle outState) {...} and restore them with onRestoreInstanceState(Bundle savedInstanceState){...}.
In onCreate method after setting up myWebView I did the following:
myWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String urlString)
{
Log.i("onPageFinished", "loadVariables("+newURL+")");
if(newURL!="")
myWebView.loadUrl("javascript:loadVariables("+"\""+newURL+"\")");
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
jsInterface = new JSInterface(this,myWebView);
myWebView.addJavascriptInterface(jsInterface, "Android");
if (savedInstanceState != null)
{
// retrieve saved variables and build a new URL
newURL = "www.yoururl.com";
newURL +="?var1=" + savedInstanceState.getInt("key1");
newURL +="?var2=" + savedInstanceState.getInt("key2");
Log.i("myWebApp","NEW URL = " + newURL);
}
myWebView.loadUrl("www.yoururl.com");
So, what it happens is that first I load the page and then I pass the variables when the page finished to load.
In javascript loadVariables function looks like this:
function loadVariables(urlString){
// if it is not the default URL
if(urlString!="www.yoururl.com")
{
console.log("loadVariables: " + urlString);
// parse the URL using a javascript url parser (here I use purl.js)
var source = $.url(urlString).attr('source');
var query = $.url(urlString).attr('query');
console.log("URL SOURCE = "+source + " URL QUERY = "+query);
//do something with the variables
}
}

Developer Sites contradict each other regading webview-shouldOverrideUrlLoading

a lot of Android developer implement their own webview.
Although a lot of questions related to this topic are discussed on stackoverflow, here is probably a cause of this lack of clarity.
To open links within your WebView, android developer define their own webview.
According to http://developer.android.com/guide/webapps/webview.html returning false in shouldOverrideUrlLoading should be used, to open the url in the current Webview.
("current" means presumably created or used lately?)
According to http://developer.android.com/resources/tutorials/views/hello-webview.html and various blogs:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
true must me returned.
Is there a mistake in one of the developer sites? It there difference between API level?
What is the cleanest and best use of shouldOverrideUrlLoading?
An answer would help our team and a lot of other developers working with android webviews.Thanks.
In case you decide to implement WebViewClient:
webView.setWebViewClient(new WebViewClient()
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
// My own condition to decide if I should skip URL loading
boolean avoidURLLoading = ...
if (avoidURLLoading)
{
// Ask the WebView to avoid loading the URL,
// I want to manage this case on my own.
return true;
}
else
{
// Let the WebView load the URL
return false;
}
};
});
If you don't implement WebViewClient, every time you'll ask the WebView to load an URL with the loadUrl method, it will ask the Activity Manager to find a proper app to load the URL (typically a web browser installed in the device).
The default implementation of shouldOverrideUrlLoading in WebViewClient is
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return false;
}
So if you just write something like this
webView.setWebViewClient(new WebViewClient());
the URL will load inside your own WebView and not in an external web browser.
You'll typically return true in shouldOverrideUrlLoading when you want to modify the URL and then load the new one with another loadUrl call or when you just want to avoid loading the URL and handle the request in a different way.
The behavior in your example
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
is equivalent to
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return false;
}
because you're telling the WebView to avoid handling the URL loading (return true), but you're also making another request with view.loadUrl(url) so in fact you end up loading the URL.
In order to open the link in the current WebView(Not the browser) you sould return false like this:
mWebView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url){
return false;
}
});
As long as you implement the setWebViewClient(..) my answer and the axample do the same thing. If you on the other hand do not implement it the browser will start instaed.

Categories

Resources