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)
Related
When creating an application i noticed it is not recognized as the variable navigator.standalone is not set. I first thought i would fix this bij setting it mannually when injecting javascript as below:
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
webView.evaluateJavascript("navigator.standalone = true;", new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.e(TAG + "jsinject", s);
}
});
}
});
webView.addJavascriptInterface(new WebAppInterface(this, webView), "Android");
However this injects to late and some javascript functions wont fire because it is not recognized as a standalone application. Is there a possibility to set the var before the page finished loading?
I replaces the function onPageFinished(WebView view, String url) with onPageStarted(WebView view, String url, Bitmap favicon) this injects the navigator var before the page is fully loaded
The Cordova plugin I'm using plays a VR video file, and is called via GoogleVRPlayer.playVideo(videoUrl, fallbackVideoUrl).
Somewhere in the .java files of the plugin, there's:
#Override
public void onLoadError(String errorMessage) {
// I want to know if this function is executed
Log.e(TAG, "Error loading video: " + errorMessage);
}
Basically, when the video fails to load, I want to set a variable in my javascript in cordova to "error", for example var video_status = "error", so I can use this information later on in my app.
I've found some answers that would possibly solve my problem, but I can't seem to integrate it the right way. I have very little experience with native plugins and Java.
Anyone who can help me with this?
Since the Cordova plugin GoogleVRPlayer launches a new Activity (VrVideoActivity), I would use a Singleton class as an interstitial data bridge between the two Activites to hold the error message.
This is because, on launching the video player activity, your app (the Cordova activity) is paused in the background and will only resume execution once the video player activity is closed.
By using the intermediate class, both the Cordova plugin and the video activity are able to share data.
So I would do something like this:
Create a new file called CordovaBridge.java in cordova-vr-player/src/android/java/neotrino/
package com.neotrino;
public class CordovaBridge {
private String errorMsg = null;
public String getErrorMsg() {return errorMsg;}
public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}
private static final CordovaBridge holder = new CordovaBridge();
public static CordovaBridge getInstance() {return holder;}
}
Modify GoogleVRPlayer.java as follows:
import com.neotrino.CordovaBridge;
#Override
public void onResume(boolean multitasking) {
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
String errorMsg = CordovaBridge.getInstance().getErrorMsg();
if(errorMsg != null){
webView.loadUrl("javascript:window.video_status = '"+errorMsg+"'");
}
}
});
}
Modify VrVideoActivity.java as follows:
import com.neotrino.CordovaBridge;
#Override
public void onLoadError(String errorMessage) {
// I want to know if this function is executed
Log.e(TAG, "Error loading video: " + errorMessage);
CordovaBridge.getInstance().setErrorMsg(errorMessage);
}
I haven't tested the above code, but in terms of an approach it should give you an approximation on which to base your solution.
Enabled Javascript on WebView. Because without JavaScipt web page image scaling is not working properly. This is my code how I am loading url in WebView:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String url = "http://nuz.uz/ekonomika-i-finansy/18651-v-2017-godu-v-uzbekistane-prekratitsya-realizaciya-lampochek-ilicha.html";
final WebView webview = (WebView) findViewById(R.id.webview);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient() {
public void onConsoleMessage(String message, int lineNumber, String sourceID) {
Log.d("Tag", message + " -- From line "
+ lineNumber + " of "
+ sourceID);
}
});
webview.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String loadingUrl) {
if (loadingUrl.equals(url)) return false;//open news link in webview
else {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(loadingUrl));
startActivity(browserIntent);
return true;
}
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){
Log.d("Tag", "Error occured: "+error.toString());
}
});
webview.loadUrl(url);
}
}
When I am running app, it is opening web page. After loading all content of page, app is crashing. I tried to show error on console it is showing following error:
12-14 02:42:06.936 25760-25760/? D/Tag: Uncaught TypeError: Cannot
call method 'init' of undefined -- From line 951 of
http://nuz.uz/ekonomika-i-finansy/18651-v-2017-godu-v-uzbekistane-prekratitsya-realizaciya-lampochek-ilicha.html
I have checked url's content and found following which is causing app crash :
<script type="text/javascript">
jQuery(document).ready(function () {
App.init();
});
</script>
line 951: App.init();
How I can solve this problem without turning off JavaScript? How to prevent WebView from crashing app?
If you look at the source code of the page, right above line 951, you'll find
<script type="text/javascript" src="/templates/nuz_uz/assets/js/app.js"></script>
This script declares the App variable to be the result of the anonymous function, but the function doesn't return anything. Therefore App is still undefined at the time jQuery fires the ready event. You basically need to fix the error on the website, your Android app is fine.
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;
}
}
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.