Inject javascript into WebChromeClient - javascript

I know, you can inject javascript into an Android WebView. I already did that. However, I load a html5/javascript web app (not my own, so I have no access to the code) and I need to inject additional javascript. But this web app does not work properly in the standard WebView. The reason for that is probably:
"By default, a WebView provides no browser-like widgets, does not enable JavaScript and web page errors are ignored."
http://developer.android.com/reference/android/webkit/WebView.html
So, I enabled Javascript, but maybe this is due to the fact that it ignores webpage errors. However in the normal Chrome browser everythings works fine without any problems.
The webview does not work although I already enabled a lot of stuff:
webView = (WebView) findViewById( R.id.webView );
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(PluginState.ON);
webView.getSettings().setDomStorageEnabled(true);
webView.setBackgroundColor(0x00000000);
webView.setWebChromeClient( new WebChromeClient() );
webView.setWebViewClient( new WebViewListener() );
CookieManager.getInstance().setAcceptCookie(true);
So, is there some possibility to inject javascript into a normal WebChromeClient?
Or do you have any other guess what else I could enable or inject into the webview?

First, you need to setWebViewClient with a class that's derived form WebViewClient:
WebView webview = new WebView();
webview.setWebViewClient(new WebClient());
webview.loadUrl("stackoverflow.com");
then in WebClient, you wait for the page to load (onPageFinished). Then you loadUrl("javascript:[your javascript here]").
public class WebClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url)
{
// Obvious next step is: document.forms[0].submit()
view.loadUrl("javascript:document.forms[0].q.value='[android]'");
}
}

It is remembered wanting to do different JavaScript related tasks and so needing to enable a bunch of options and even set the browser type...here is those config options:
webView.setWebChromeClient(webChromeClient);
webView.setWebViewClient(new InsideWebViewClient(getBaseContext(), webView));
WebSettings settings = webView.getSettings();
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setBuiltInZoomControls(false);
settings.setUseWideViewPort(true);
settings.setJavaScriptEnabled(true);
settings.setSupportMultipleWindows(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLoadsImagesAutomatically(true);
settings.setDomStorageEnabled(true);
settings.setLoadWithOverviewMode(true);
settings.setMediaPlaybackRequiresUserGesture(false);
// Call private class InsideWebViewClient
settings.setPluginState(WebSettings.PluginState.ON);
settings.setAllowFileAccess(true);
// settings.setUserAgentString("Mozilla/5.0");
settings.setUserAgentString("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36");
// webView.setInitialScale(50);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationContext().getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE))
{ webView.setWebContentsDebuggingEnabled(true); }
}
for reference that was used with the same basic following:
https://github.com/cprcrack/VideoEnabledWebView/blob/01c7f758a409fabbc501cdf24efdf5b77400280f/app/src/main/java/name/cpr/ExampleActivity.java

Related

Start an Android activity from an HTML link in a webview

In an Android activity I am displaying a webview.
WebView myWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/html/cloud.html");
The webview loads a local HTML file that builds a cloud of keywords with a javascript file. (source: http://www.goat1000.com/tagcanvas.php)
<script src="tagcanvas.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
try {
TagCanvas.Start('myCanvas','tags',{depth: 0.8, maxSpeed: 0.03});
} catch(e) {
// something went wrong, hide the canvas container
document.getElementById('myCanvasContainer').style.display = 'none';
}
The keywords are generated from a list of HTML links defined in the HTML file
<div id="tags">
<ul>
<li>keyword1</li>
<li>keyword2</li>
<li>keyword3</li>
</ul>
</div>
When a user taps on a link, instead of staying in the webview and going to the corresponding location, I would like him to start a new Android activity, so obviously with Android code
I have found resources showing an example of how to make Android and Javascript "communicate" with an interface but I didn't manage to make it work in my case.
Edit:
My implementation thanks to the answer of Vlad
myWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent(Act1.this, Act2.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //ugly solution to avoid starting 2 activities, not ideal but it works
startActivity(intent);
return true; //I always return true because I never want to open an HTML link
}
});
You can set a custom WebViewClient to the WebView, and intersect url loading in it:
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// check the URL, and do whatever you need to do according to the URL
// return true; // if you handled URL, and WebView should not load it
return false; // for the WebView to load the URL
}
});

Android, calling the browser from javascript inside a WebView

I try to call the browser of my device loading a page inside a WebView that contains:
window.open(
'http://www.stackoverflow',
'_blank'.
);
I need to do this from the html that is loaded into the WebView
but i have no success, any idea!?
There are several things you need to do in your app:
Use setJavaScriptCanOpenWindowsAutomatically as #ajpolt says. This will allow window.open to not fail.
Enable setSupportMultipleWindows. This makes WebView to actually attempt opening a new window. Otherwise, it will be opening the URL in the same WebView.
Hook up to WebChromeClient.onCreateWindow callback and create a new WebView instance there. For this new instance, you need to set WebViewClient that will launch the intent from shouldOverrideUrlLoading.
Below is sample code:
WebView webView = (WebView)findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setSupportMultipleWindows(true);
webView.setWebChromeClient(new ChromeClient());
And this is the ChromeClient:
class ChromeClient extends WebChromeClient {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView tempWebView = new WebView(MainActivity.this);
tempWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivity(browserIntent);
return true;
}
});
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(tempWebView);
resultMsg.sendToTarget();
return true;
}
}
You are probably missing a setting on your webview.
Try using setJavaScriptCanOpenWindowsAutomatically in your settings, like this:
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

Page that works in Android Browser doesn't work in WebView

We are designing an app that as part of its functionality needs to let users interact with this page:
http://m.bridgestonetire.com/catalog
This page works fine in the device browser and formerly worked in our webview, but now users cannot click on the Year / Make / Model buttons. The other functions on the page ARE clickable.
In searching here on similar issues the answers always seem to be around changing the underlying webpage, which we cannot do. Is there anything we can do to make our webview more compatible with that page? Webview settings are as follows:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getActionBar().hide();
Constants.setCViewAndRenderFonts(this, R.layout.web_layout);
adviser = (WebView)findViewById(R.id.tireAdvisor);
WebViewClient tclient = new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
L.d( "loading url: " + url);
view.loadUrl(url);
return true;
}
};
adviser.setWebViewClient(tclient);
adviser.getSettings().setJavaScriptEnabled(true);
adviser.getSettings().setSupportZoom(true);
adviser.getSettings().setUseWideViewPort(false);
adviser.getSettings().setLoadWithOverviewMode(true);
adviser.getSettings().setGeolocationEnabled(true);
adviser.setVerticalScrollBarEnabled(false);
adviser.setHorizontalScrollBarEnabled(false);
adviser.getSettings().setAppCacheEnabled(true);
adviser.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36");
String mobileUrl = "http://m.bridgestonetire.com/catalog";
String desktopUrl = "http://m.bridgestonetire.com/catalog";
adviser.loadUrl(desktopUrl);
adviser.setBackgroundColor(0x00000000);
adviser.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
adviser.clearCache(true);
adviser.clearFormData();
android.webkit.CookieManager.getInstance().removeAllCookie();
I have realized you are using JQuery in your web page, and the link that "data-href" is tryin to open is a .json file.
for example "MAKE" option :
<input type="hidden" name="make" value="" data-href="http://m.bridgestonetire.com/bin/fst/api/vehicle/1/make.json" />

Android webview "location.replace" doesn't work

I have an Android webview with a page that redirects to another page, using location.replace(url).
Lets say that I have page "A" that redirects to page "B" (using location.replace). When pressing "back" button from page "B", the page returns to page "A", which redirects it to page "B" again.
When I debug the history api (history.length), I can clearly see that on page "B" the length has incremented in "1" (only on Android 4.X webview. On iOS / web browser / Android 2.X it remains the same), which is a bug! (location.replace shouldn't change history.lenght!)
I work with Yaniv on this project and we found the cause of the problem, it was introduced when we tried to add mailto: links handling according to this answer.
The answer suggested using the following extending class of WebViewClient:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
The problem was that explicitly telling the WebViewClient to load the URL and returning true (meaning "we handled this") added the page to the history. WebViews are quite capable of handling regular URLs by themselves, so returning false and not touching the view instance will let the WebView load the page and handle it as it should.
So:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
return false;
}
}
}
function locationReplace(url){
if(history.replaceState){
history.replaceState(null, document.title, url);
history.go(0);
}else{
location.replace(url);
}
}
Try this way..
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView mainWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = mainWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mainWebView.setWebViewClient(new MyCustomWebViewClient());
mainWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mainWebView.loadUrl("file:///android_asset/www/A.html");
}
Or get help from this and this link

webview don't display javascript windows.open()

I have a WebView in which i display web content which i have no control over. The content displays fine, but have links which spawn a popup window. The javascript function that does that looks like this:
function getEntry(id) {
var win = window.open('', 'Booking',
'resizable=yes,scrollbars=yes,status=no,width=500,height=400');
win.document.location = '/some/url/1-' + id ;
}
I can't easily change this, and if the people responsible for the page i download would change it, i guess my app would fail miserably...
My WebView setup in the activity looks like this:
_webview = new WebView(this);
setContentView(_webview);
final Activity activity = this;
_chromeClient = new MyChromeClient();
_webview.setWebChromeClient(_chromeClient);
//I experimented with changing user agent, in case that would have any effect, it didn't...
_webview.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1");
_webview.setWebViewClient(new MyWebViewClient());
_webview.getSettings().setJavaScriptEnabled(true);
_webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
_webview.getSettings().setSupportZoom(true);
_webview.getSettings().setBuiltInZoomControls(true);
_webview.getSettings().setDomStorageEnabled(true);
//Cache settings...
_webview.getSettings().setAppCacheMaxSize(1024*1024*8);
_webview.getSettings().setAppCachePath("/data/data/com.your.package.appname/cache");
_webview.getSettings().setAllowFileAccess(true);
_webview.getSettings().setAppCacheEnabled(true);
MyWebClient:
private class MyWebViewClient extends WebViewClient {
#Override
public void onLoadResource(WebView view, String url) {
Log.d("MyWebViewClient",url);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
showProgressDiag();
Log.d("MyWebViewClient","shouldOverride... : " + url);
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url){
hideProgressDiag();
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
if(failingUrl.equals("file:///android_asset/html/error.html")){
hideProgressDiag();
Toast.makeText(_context, "Error! Check internet connection, or try again later...", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(_context, failingUrl, Toast.LENGTH_SHORT).show();
view.loadUrl("file:///android_asset/html/error.html");
}
}
}
MyChromeClient:
private class MyChromeClient extends WebChromeClient{
#Override
public void onProgressChanged(WebView view, int progress) {
Pdiag.setProgress(progress * 100);
}
}
When clicking one of the links that points to the javascript function all that happens is that the WebView turns grey, without going through shouldOverrideUrlLoading(). When i hit the back key the app exits, meaning that nothing was placed in the nav history of the WebView. Sometimes nothing happens, but then the shouldOverrideUrlLoading() do run and from a Log.d() i can see that the correct URL for the popup has been given to the WebView.
The thing is, on very rare occasions it shows up fine, but i have no clue how to reproduce it, and wether it actually shows in a popup.
I'm lost... And quite frustrated... Thinking of watching a bad sitcom instead :(
EDIT:
Actually, maybe the URL wasn't all that correct after all... In Firefox the URL ends with "X<<<<" but in my Log.d() output it ends with "X%3C%3C%3C%3C"... I'll investigate if i could change that...
EDIT 2:
Nope, didn't do anything... The URL is identical to the one in Firefox...
First of all, you need to set the following settings on your WebView:
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportMultipleWindows(true);
Then you need to attach a WebChromeClient that overrides onCreateWindow. Your implementation of this method can create a new web view, and display it inside a dialog:
webView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView newWebView = new WebView(MyActivity.this);
WebSettings webSettings = newWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Other configuration comes here, such as setting the WebViewClient
final Dialog dialog = new Dialog(MyActivity.this);
dialog.setContentView(newWebView);
dialog.show();
newWebView.setWebChromeClient(new WebChromeClient() {
#Override
public void onCloseWindow(WebView window) {
dialog.dismiss();
}
});
((WebView.WebViewTransport)resultMsg.obj).setWebView(newWebView);
resultMsg.sendToTarget();
return true;
}
});
Don't forget to set the new web view to the resultMsg, send it to its target and return true, as mentioned in the API documentation.
Please check with adding this -
getSettings().setSupportMultipleWindows(true);

Categories

Resources