I have written Javascript code that contain callback handler to my android app and inject it from my android code. It fires call back event when we perform play/pause action of video in webview and return event in callback. We are injecting Javascript code form both plateform (iOS and Android)
But unfortunately in iOS, all event value data is getting but in Android it is showing "undefined"
Below is my JavaScript code that is injecting from Android
webView.addJavascriptInterface(new Object() {
#JavascriptInterface
public void getEvent(String data) {
Toast.makeText(getContext(), data , Toast.LENGTH_SHORT).show();
Log.w("TAGGG", "callBackEvent: " + data.toString() );
}
}, "abc");
#Override
public void onPageFinished(WebView view, String url) {
tvErrorMessage.setVisibility(View.INVISIBLE);
String scriptThree = "javascript:window.myApp_event =(function() {" +
"function notifyApp(event) {" +
"var myCallback = console.log(event);"+
"abc.getEvent(event);" + // This is callback for Android
"}" +
"var oExistingEvents = window.myApp_event || [];" +
"oExistingEvents.forEach(notifyApp);" +
"return {" +
"push: function(event) {" +
"notifyApp(event);" +
"}" +
"}" +
"})();";
webView.loadUrl(scriptThree);
}
How can we get that event name that is get in iOS but not in Android?
I am stucked in one functionality. I am storing login credentials in my app for website. And there is one LOGIN button is there. When I hit that button, it will redirect to webview with website. And if there is any email and password, my login credentials will be filled there.
Example: I have stored facebook credentials in my app. And my webview is loading with https://m.facebook.com and when it will finish loading my stored login credentials will be filled there. So I just need to hit login button from webview to move forward.
For my app I am using following code. Which is not working for most website. Can anyone help me how to figure out this issue? Or does anyone has better idea to achieve this kind of functionality?
wvAutofill.loadUrl("https://mobile.twitter.com/login");
wvAutofill.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
final String js = "javascript: var x = document.getElementsByTagName(\"form\")[0].getElementsByTagName('input');" +
"for (var i = 0; i < x.length; i++) {" +
"\nconsole.log(x[i].type);" +
"var type = x[i].type;" +
"if (type=='text'){" +
"x[i].value=\"abc#gmail.com\";" +
"};" +
"if (type == 'password'){\n" +
"x[i].value=\"abc123\";" +
"}; " +
"if (type == 'button' || type == 'submit' || document.getElementsByTagName(\"button\")[0].tagName == \"button\"){" +
"x[i].click();" +
"}; " +
"}";
view.loadUrl(js);
}
});
I am trying to get Intent data to the loaded WebView.
Before the intent, There was a EditText, and I originally used the values to login to myURL site with the WebView inside that Activity whitch had userID and userPW (at the site).
But for better design, I've move the Webview to another activity and sends the ID,PW with Bundle.
The problem is that the String variable email and password seems to be set well, but when i try to use the same code i used before, it doesn't work well.
Is there some rules in Android that i can't pass the variables directly without user input? Does someone know how to solve this problem?
Below is the code i'm currently stuck on
public class MyWeb extends Activity{
WebView webview;
String email;
String password;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_myweb);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
email = bundle.getString("ID");
password = bundle.getString("PW");
webview = (WebView)findViewById(R.id.logIn);
webview.setWebViewClient(new WebClient());
webview.getSettings().setDatabaseEnabled(true);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("myURL");
login(email, password);
}
private void login(String id, String pw){
webview.loadUrl("javascript: {" +
"document.getElementById('userID').value = '"+email +"';" +
"document.getElementById('userPW').value = '"+password+"';" +
"var a = document.getElementsByTagName('input');" +
"a[2].CheckSubmit(); };");
webview.loadUrl("javascript:CheckSubmit()");
}
webview.setWebViewClient(new WebClient() {
#Override
public void onPageFinished(WebView view, String url) {
webview.loadUrl("javascript: {" +
"document.getElementById('userID').value = '" + email + "';" +
"document.getElementById('userPW').value = '" + password + "';" +
"var a = document.getElementsByTagName('input');" +
"a[2].CheckSubmit(); };");
webview.loadUrl("javascript:CheckSubmit()");
}
});
Solved, I guess it was because of the JS was called before the webpage load thinking that the Activity before this loads all the page while i type in the fields
I'm having a problem with my code when running on a Android 4.4.2 KitKat (API 19) emulator...
When I emulate my project on a Android 4.3 (API 18) emulator, it works normally and creates the mathematical expressions with MathJax:
Image of emulator
But when I use a Android 4.4.2 emulator, the app don't work correctly:
Image of emulator
Here is the code of my project:
package com.testes.testesapp;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements View.OnClickListener {
private int exampleIndex = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
//webView.getSettings().setBuiltInZoomControls(true);
webView.loadDataWithBaseURL("http://test", "<script type='text/x-mathjax-config'>"
+ "MathJax.Hub.Config({ "
+ "showMathMenu: false, "
+ "jax: ['input/TeX','output/HTML-CSS'], " // output/SVG
+ "extensions: ['tex2jax.js','toMathML.js'], "
+ "TeX: { extensions: ['AMSmath.js','AMSsymbols.js',"
+ "'noErrors.js','noUndefined.js'] }, "
// + "'SVG' : { blacker: 30, "
// + "styles: { path: { 'shape-rendering': 'crispEdges' } } } "
+ "});</script>"
+ "<script type='text/javascript' "
+ "src='file:///android_asset/MathJax/MathJax.js'"
+ "></script>"
+ "<span id='math'></span>","text/html","utf-8","");
EditText edit = (EditText) findViewById(R.id.edit);
edit.setBackgroundColor(Color.LTGRAY);
edit.setTextColor(Color.BLACK);
edit.setText("");
Button btnShow = (Button) findViewById(R.id.btnShow);
btnShow.setOnClickListener(this);
Button btnClear = (Button) findViewById(R.id.btnClear);
btnClear.setOnClickListener(this);
Button btnExample = (Button) findViewById(R.id.btnExample);
btnExample.setOnClickListener(this);
}
private String doubleEscapeTeX(String s) {
String t="";
for (int i=0; i < s.length(); i++) {
if (s.charAt(i) == '\'') t += '\\';
if (s.charAt(i) != '\n') t += s.charAt(i);
if (s.charAt(i) == '\\') t += "\\";
}
return t;
}
private String getExample(int index) {
return getResources().getStringArray(R.array.tex_examples)[index];
}
public void onClick(View v) {
if (v == findViewById(R.id.btnShow)) {
WebView webView = (WebView) findViewById(R.id.webview);
EditText edit = (EditText) findViewById(R.id.edit);
webView.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
+ doubleEscapeTeX(edit.getText().toString()) + "\\\\]';");
webView.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
}
else if (v == findViewById(R.id.btnClear)) {
WebView webView = (WebView) findViewById(R.id.webview);
EditText edit = (EditText) findViewById(R.id.edit);
edit.setText("");
webView.loadUrl("javascript:document.getElementById('math').innerHTML='';");
}
else if (v == findViewById(R.id.btnExample)) {
WebView webView = (WebView) findViewById(R.id.webview);
EditText edit = (EditText) findViewById(R.id.edit);
edit.setText(getExample(exampleIndex++));
if (exampleIndex > getResources().getStringArray(R.array.tex_examples).length - 1)
exampleIndex=0;
webView.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
+ doubleEscapeTeX(edit.getText().toString()) + "\\\\]';");
webView.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
}
}
}
When I press the "Example" or the "Show" button, LogCat emits the errors:
I/chromium(1254): [INFO:CONSOLE(1)] "Uncaught TypeError: Cannot set property 'innerHTML' of null", source: http://test/ (1)
I/chromium(1254): [INFO:CONSOLE(1)] "Uncaught ReferenceError: MathJax is not defined", source: http://test/ (1)
I have no idea how to fix this problem, and would like somebody's help to solve this. Thanks.
I got this problem too.
Here is my solution:
change your base URL from "http://test" to "http://test/"
change this code webView.loadUrl(..) to webView.evaluateJavascript(..);. Especially for code where we want to load innerHTML. Don't forget to add anotation #TargetApi(Build.VERSION_CODES.KITKAT) because it's only for Android 4.4 and above
never put webView.loadWithBaseUrl(..) in the same process with webView.loadUrl(..). Because If webView.loadUrl(..) was loaded before webView.loadWithBaseUrl(..) finished, it will raise error as OP stated above.
For number 3, your codes is already conform with this (because in your codes, webView.loadUrl(..) execution was already separated with webView.loadWithBaseUrl(..) by using OnClick event. So, don't pay attention to it.
But if your apps need to load them at one event, consider to separate them by using this code:
`
private void initiateWebView(){
webViewEquationDisplay.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
loadUrlKitKat(equationSymbolFinal+equationToBeDisplayedFinal);
}
else{
webViewEquationDisplay.loadUrl("javascript:document.getElementById('math').innerHTML='<font color=\"yellow\">`"+equationToBeDisplayedFinal+"`</font>';");
}
webViewEquationDisplay.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
}
});
final String mathJaxOfflineUrl = "file:///android_asset/MathJax/MathJax.js";
webViewEquationDisplay.loadDataWithBaseURL("http://bar/", "<script type='text/x-mathjax-config'>"
+"MathJax.Hub.Config({ "
+"showMathMenu: false, "
+"jax: ['input/AsciiMath','output/HTML-CSS'], "
+"extensions: ['asciimath2jax.js'], "
+"AsciiMath: { fixphi: true, useMathMLspacing: true, displaystyle: false, decimalsign: \".\" }, "
+"});</script>"
+"<script type='text/javascript' "
+"src='"+mathJaxOfflineUrl+"'"
+"></script><span id='math'></span>","text/html","utf-8","");
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private void loadUrlKitKat(String param){
webViewEquationDisplay.evaluateJavascript("javascript:document.getElementById('math').innerHTML='<font color=\"#97FD97\">`"+param+"`</font>';",null);
}
`
good luck
I had the same problem when I moved different javascript functions out of the main page to an separate .js file. For some reason, Android can't find externally-loaded JavaScript webview functions from Java - only the ones in the main page. Once I moved the function back from the JS file, it immediately started working.
Try making a "proxy" function like this directly inside the main HTML:
function proxy() {
call_some_other_function_from_JS_file();
}
This worked for me. I'm sure there must be a way to get find these functions, because I didn't have this problem on iOS. Someone please comment if you know a better way.
webview.evaluateJavascript("javascript:document.getElementById('math').innerHTML='"+doubleEscapeTeX(questn)+"';",null);
webview.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
This is the sollution for api 19 or above
I need to get some properties of an html page which is loaded in a webview.
Something similar to what is here: stringByEvaluatingJavascriptFromString (iOS method, what is Android equivalent?)
So I have a JavaScriptInterface:
class MyJavaScriptInterface {
#android.webkit.JavascriptInterface
public void jsCallback(String jsResult) {
// your code...
Log.d("Debug", jsResult);
}
}
ant then here is the JS I use to get the string I need:
webView.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
webView.loadUrl("javascript:( "
+ "function () { "
+ "var htmltag = document.getElementsByTagName(\"html\");"
+ "var dataStr = htmltag[0].getAttribute(\"some-data-property-i-need\"); "
+ "console.log(window.HTMLOUT);"
+ "window.HTMLOUT.jsCallback(dataStr); } ) ()");
now in the console I see this traces:
06-02 01:14:06.409: V/CallNative fired:(26789): objc://domReady
06-02 01:14:06.464: I/Web Console(26789): undefined at null:1
06-02 01:14:06.480: E/Web Console(26789): Uncaught TypeError: Cannot call method 'jsCallback' of undefined at null:1
and I have no idea why "window.HTMLOUT" is undefined.
Please note that it was working at a point and then I modified a bit the JS part but I still cannot figure it out what could be the problem.
JS code can be executed after the whole page is loaded, have a try at this way:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// Call JS code here
}
});
webView.loadDataWithBaseURL(null, "<html></html>", "text/html", "UTF-8", "");
If previous method does not work, please have a try at HTMLOUT.jsCallback(dataStr) instead of window.HTMLOUT.jsCallback(dataStr).