I'm trying to access my Java method helloWorld(); using JavaScriptInterface in Android, from the page I'm viewing using WebView
I'm a little new to this, and I don't know why I'm not getting the value to my html page
This is the Android code I'm using:
WebView web;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
web = (WebView) findViewById(R.id.webview01);
JavaScriptInterface jsInterface = new JavaScriptInterface(this);
web.getSettings().setJavaScriptEnabled(true);
web.addJavascriptInterface(jsInterface, "JSInterface");
web.getSettings().setUseWideViewPort(true);
web.getSettings().setLoadWithOverviewMode(true);
web.setWebViewClient(new myWebClient());
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl("http://exampleweb:10110/exWeb/deposits.jsp");
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
}
public class JavaScriptInterface {
private Activity activity;
public JavaScriptInterface(Activity activity) {
this.activity = activity;
}
#JavascriptInterface
public String helloWorld(){
return("hello world");
}
}
}
This is the JavaScript code I've been using (on the page I'm viewing with WebView)
HTML button
<td> <button type="button" class="btn btn-xs btn-primary connectToAndroid">Test android</button></td>
JavaScript
$(".connectToAndroid").on('click', function () {
var val = window.JSInterface.helloWorld();
alert(val);
});
Does anyone know what I'm doing wrong here? I just want to alert an "Hello World" from android in my HTML page.
Any pointers are greatly appreciated!
Try by adding this line of code before loading the url and make sure you reference your jQuery library in the html.
web.setWebChromeClient(new WebChromeClient(this));
This is very weird, I tried using this a couple of hours ago:
$(".connectToAndroid").on('click', function () {
var val = Android.helloWorld();
alert(val);
});
Then I changed it, it didn't say Android anymore,
yet I kept getting an error saying:
Uncaught ReferenceError: Android is not defined
And after a while I figured, Android.helloWorld(); must be cached somehow in my webview app or something.
So, I changed back to this:
$(".connectToAndroid").on('click', function () {
var val = Android.helloWorld();
alert(val);
});
And added this:
web.addJavascriptInterface(jsInterface, "Android");
And now it works like a charm, as it should have from the beginning if it wasn't for some cache somewhere,
Can anyone explain why this happens? Does android webview actually cache javascript code? And can I prevent this behaviour in the future somehow? Cache bothers a lot when coding/testing new stuff.
Related
I'm a beginner at android.
I used javascript method in android. And I want to call it when the app is loaded for first time.
For example,
testMethod = function(str) {
alert("hi" + str);
}//javascript
and
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDefaultTextEncodingName("utf-8");
mWebView.loadUrl("file:///index.html");
mWebView.addJavascriptInterface(androidBridge, "jsinterface");
mWebView.loadUrl("javascript:testMethod('javascript')");
}
What I was thinking here is the alert will pop up immediately when I start the app.
But nothing happens.
About this, I have two questions.
1.Can I call and use the javascript method in Android's onCreate method?
2.If it is possible, How can I do?
if you want to show a popup on start just use the default AlertDialog. see the code below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showMessage("My Message Here", "Title here");
}
private void showMessage(String data, String title){
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(data)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue
}
})
.show();
}
check out whether index.html is REALLY loaded. I guess that webview didn't load your html properly, bcz it's not an invalid file path. try file:///mnt/sdcard/index.html. (or something likely)
try to put mWebView.loadUrl("javascript:testMethod('javascript')") in view.post or view.postDelayed.
isssue in Webview
I load pdf files using this url inside a webview " http://staging-argo.ephronsystems.com/content.php?type=view&docType=category&fileId=49&menuID=44"
in this page contains touch jquery plugin.
Thanks for help
You can use original pdf file http://staging-argo.ephronsystems.com/admin/uploads/category_files/ARGO BOND REQUEST FORM.pdf
and for viewing purpose you can use Google Docs Viewer
https://docs.google.com/viewer?url=http://staging-argo.ephronsystems.com/admin/uploads/category_files/ARGO BOND REQUEST FORM.pdf
try this.
web=(WebView)findViewById(R.id.web);
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setPluginState(WebSettings.PluginState.ON);
web.getSettings().setAllowFileAccess(true);
web.getSettings().setSupportZoom(false);
web.setWebViewClient(new WebViewClient());
loadUrl();
And loadUrl() ->
#JavascriptInterface
public void loadUrl() {
web.post(new Runnable() {
#Override
public void run() {
web.loadUrl(url);
}
});
}
And this.
private class WebViewClient extends android.webkit.WebViewClient
{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return true;
}
}
Since upgrading my nexus 4 to Android kitkat, my application stopped working. I was using javascript methods in webview but now my methods are not called. This is how i setup webview and load my javascripts:
mWebview.getSettings().setJavaScriptEnabled(true);
JavaScriptInterface jsi = new JavaScriptInterface(mCtx);
mWebview.addJavascriptInterface(jsi, ANDROID_BRIDGE);
mWebview.setWebViewClient(new WebClient());
mWebview.setWebChromeClient(new OwnChromeClient());
mWebview.setWebContentsDebuggingEnabled(true);
mWebview.loadUrl("about:blank"); //load dummy url to onPageFinished called in webViewClient
and my webClient:
public class WebClient extends WebViewClient {
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Log.e(WebClient.class.getSimpleName(), description + " code "
+ errorCode);
}
/**
* Load javascript into webview
*/
#Override
public void onPageFinished(WebView view, String url) {
ECalcMarblesWrapper wrapper = new ECalcMarblesWrapper(mCtx);
String javascripts = wrapper.getJavascripts();
String content = String.format(jsHtmlContainer, javascripts,
jsHelpFunctions);
view.loadUrl("javascript: " + content);
}
}
all loading methods are called but when i call any of javascript methods, this error is printed out to console:
Uncaught ReferenceError: initForm is not defined
where initForm is my javascript method.
On api 18 application is doing just fine, i have javascript annotation in my methods
If the target version of the application is set to 17 or higher you need to add annotation #JavascriptInterface above each method you want to export to the web view.
everything changes in Android kitkat for webview and javascript. you need to use evaluateJavascript()
check here: https://developer.android.com/guide/webapps/migrating.html
and here: https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String, android.webkit.ValueCallback)
I have some problem with calling a JavaScript function in a WebView and getting response in the app (on my Galaxy Tab 2 '10). I call the js-function directly after content loading. According this one solution i use a PictureListener
webView.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
webView.loadUrl("javascript: JsImpl.init('{response}');");
}
});
it works fine: when content is loaded, onNewPicture always is started.
"javascript: JsImpl.init('{response}') loads js that calls:
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
In the log i see D/JsImpl(18400): {response}. It seems to be everything okay but...
When I switch my tab on a landscape or portrait mode the WebView is recreated, onNewPicture are started but the method public void init(String json) in the JsImpl is often not called at all!
So if i change orientation, sometimes js works, sometimes doesn't work. No exception, no errors...
Who faced with the same problem?
Below is full code
public class NextActivity extends Activity {
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
final WebView wv = (WebView) findViewById(R.id.WebView);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JsImpl(), "JsImpl");
wv.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
wv.loadUrl("javascript: JsImpl.init('{responce}');");
}
});
}
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
}
html code is not needed here, just put on the assets dir an empty html file index.html.
EDIT:
I've found one soution but i dont know exactly is it correct varion. But it works.
I added handler loop
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isJSSetup) return;
Log.i("handler-loop", "JS didn't handle. Reload page");
wv.loadUrl(CONTENT_PAGE);
handler.postDelayed(this, 1000);
}
}, 1000);
when #JavascriptInterface init(String json) is called, isJSSetup became true. In handler loop i check if JS is setup or no if (isJSSetup) return;. If no - i reload URL again wv.loadUrl(CONTENT_PAGE) and try to call init(String json). So long as it is not going to work. It's hardcode, so i'm still looking for a good solution.
I hope this will help, but I can't say for sure because you are not showing how your WebView is restored after orientation changes.
I was having very hard time making my nested fragments to work properly after orientation changes. I wanted to retain the form values and all functionality during screen rotations. It all worked fine except the JavascriptInterface was NEVER working after orientation changes.
My WebView is restored in the onCreateView. I had to remove the restoreState call for my WebView and it all works now.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layoutT4, container, false);
webView = (WebView) rootView.findViewById(R.id.webViewT4);
prepareBrowser(); // the browser is initiated here including the JavascriptInterface
if (webView != null) {
String URL = (savedInstanceState == null) ? "" : savedInstanceState.getString("URL");
if (URL.equals("")) {
webView.loadUrl("yourhome.html");
} else {
//webView.restoreState(savedInstanceState.getBundle("webViewBundle")); // this line was preventing the JavascriptInterface to work properly
webView.loadUrl(URL); // this is saved in onSaveInstanceState - I just reopen the URL here, the PHP page will take care of reloading the data
}
}
return rootView;
}
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);