I am using webview to render html file and i used java script to highlight (Hello) word in html
public class MyActivity extends Activity{
WebView myWebView;
TextView myResult;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myResult = (TextView)this.findViewById(R.id.myResult);
myWebView = (WebView)this.findViewById(R.id.myWebView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/index.html");
String txt="Hello";
myWebView.loadUrl("javascript:var text='"+ txt+ "';if (window.find) {document.designMode ='on';var sel = window.getSelection();sel.collapse(document.body, 0);while (window.find(text)) { document.execCommand('HiliteColor', false, 'red');sel.collapseToEnd();}document.designMode = 'off';} else if (document.body.createTextRange) { var textRange = document.body.createTextRange(); while (textRange.findText(text)) {textRange.execCommand('BackColor', false, 'red'); textRange.collapse(false);}}");
myWebView.addJavascriptInterface(new JavaScriptHandler(this), "MyHandler");
}
and this my html
<html>
<head>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
this code is run good in debug mode i mean that it already highlight (hello) but in running mode it did not why???????????
i do not know what it mean that running good in debug mode but not in running mode?
Related
Problem: I cant seem to find a way for javafx webengine to fire javascript function if I use a java String object with multiple line.
If I enter the following example in html: "asd" ENTER "qwe" in the input textArea then CLICK send button. The following java code wont run:
webEngine.executeScript("onRecieveMsg('" + msg + "')");.
But it will work if I don't use ENTER in input textArea.
Please help me
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Chat</title>
</head>
<script type="text/javascript">
function onSendMsg(){
var msg = document.getElementById("inputTextArea").value;
document.getElementById("inputTextArea").value = "";
java.onSendMsg(msg);
}
function onRecieveMsg(msg){
var msg = msg;
msg = document.getElementById("outputTextArea").value + msg;
document.getElementById("outputTextArea").value = msg + "\n";
}
</script>
<body>
<h1>Output</h1>
<textarea id="outputTextArea" rows="10" cols="50" readonly></textarea>
<h1>Input</h1>
<textarea id="inputTextArea" rows="4" cols="50"></textarea>
<button id="sendBtn" onclick="onSendMsg()">Send</button>
</body>
</html>
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class ViewFx extends Application {
//VARIABLES
private WebView webView;
private WebEngine webEngine;
private WebEngineListener webEngineListener;
private JsBridge jsBridge;
//CONTRUCTOR
//METHODS
#Override
public void start(Stage stage) {
webView = new WebView();
webEngine = webView.getEngine();
webEngine.load(getClass().getResource("view.html").toExternalForm());
jsBridge = new JsBridge();
webEngineListener = new WebEngineListener(jsBridge);
webEngine.getLoadWorker().stateProperty().addListener(webEngineListener);
stage.setScene(new Scene(webView));
stage.setWidth(600);
stage.setHeight(700);
stage.show();
}
//INNER CLASS
private class WebEngineListener implements ChangeListener<State> {
//VARIABLES
private JsBridge jsBridge;
private JSObject jsobj;
//CONSTRUCTOR
private WebEngineListener(JsBridge jsBridge) {
this.jsBridge = jsBridge;
}
//METHODS
#Override
public void changed(ObservableValue<? extends State> observable, State oldState, State newState) {
if(newState == State.SUCCEEDED) {
jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("java", jsBridge);
}
}
}
public class JsBridge {
//VARIABLES
//CONTRUCTOR
//METHODS
public void onSendMsg(String msg) {
webEngine.executeScript("onRecieveMsg('" + msg + "')");
}
}
public static void main(String[] args) {
launch(args);
}
}
Multiline string literals neither work in JavaScript nor in java. In case of a multiline message being received you simply execute invalid JavaScript code:
message received
asd
qwe
Executed javascript
onRecieveMsg('asd
qwe')
You need to escape newline instead of including them in the script. There are a few more characters that require being quoted. You could use a method like this to get a properly quoted string:
public static String toJavaScriptString(String value) {
value = value.replace("\u0000", "\\0")
.replace("'", "\\'")
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
return "\""+ value+"\"";
}
Below I attached the code to be executed with webview.
NOTE: JAVASCRIPT SHOULD BE ENABLED
ANYONE HELP ME TO RUN THIS HTML STRING IN WEBVIEW
<!DOCTYPE html>
<html>
<body>
<!-- Markup for HTML (Factors in Placement and Enrollment of Primary
Care Patientsin YMCA's Diabetes Prevention Program, Bronx, New
York,2010-2015) --><div class='rid_08184eef_309335'
data-apiroot='//tools.cdc.gov/api' data-mediatype='html'
data-mediaid='309335' data-stripscripts='true' data-stripanchors='false'
data-stripimages='false' data-stripcomments='true'
data-stripstyles='true' data-cssclasses='syndicate' data-ids=''
data-xpath='' data-oe='utf-8' data-of='xhtml' data-ns='cdc'
data-postprocess='' data-nw='true' data-iframe='true'
data-cdc-widget='syndicationIframe'
data-apiembedsrc='skins/larry//tools.cdc.gov/api/embed/html/js/embed-2.0.3.js'
data-iframeembedsrc='skins/larry//tools.cdc.gov/TemplatePackage/contrib/widgets/tp-widget-external-loader.js'></div><script
src='skins/larry//tools.cdc.gov/TemplatePackage/contrib/widgets/tp-widget-external-loader.js'
></script><noscript>You need javascript enabled to view this content or go to <a href='skins/larry//tools.cdc.gov/api/v2/resources/media/309335/noscript'>source URL</a>.</noscript>
</body>
</html>
I followed this link for basic setup. Nothing helped
BELOW I ATTACHED MY JAVA CODE
public class WebtestActivity extends Activity {
WebView webtest;
final Activity activity = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.webviewtesting);
webtest=(WebView)findViewById(R.id.webtest);
String htmlString = "<!-- Markup for HTML (How to Prevent Cancer or Find It Early) --><div class=\"rid_ec9fb40c_123238\" data-apiroot=\"//tools.cdc.gov/api\" data-mediatype=\"HTML\" data-mediaid=\"123238\" data-stripscripts=\"false\" data-stripanchors=\"false\" data-stripimages=\"false\" data-stripcomments=\"false\" data-stripstyles=\"false\" data-cssclasses=\"syndicate\" data-ids=\"\" data-xpath=\"\" data-oe=\"UTF-8\" data-of=\"XHTML\" data-ns=\"\" data-postprocess=\"\" data-nw=\"true\" data-iframe=\"true\" data-cdc-widget=\"syndicationIframe\" data-apiembedsrc=\"//tools.cdc.gov/api/embed/html/js/embed-2.0.3.js\" data-iframeembedsrc=\"//tools.cdc.gov/TemplatePackage/contrib/widgets/tp-widget-external-loader.js\" data-font=\"\"></div><script src='//tools.cdc.gov/TemplatePackage/contrib/widgets/tp-widget-external-loader.js' ></script><noscript>You need javascript enabled to view this content or go to <a href='//tools.cdc.gov/api/v2/resources/media/123238/noscript'>source URL</a>.</noscript>";
webtest.getSettings().setJavaScriptEnabled(true);
webtest.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress)
{
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if(progress == 100)
activity.setTitle(R.string.app_name);
}
});
webtest.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
{
// Handle the error
Log.d("des===",description);
Log.d("failingUrl===",failingUrl);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
Log.d("shouldlLoading===",url);
view.loadUrl(url);
return true;
}
});
webtest.loadData(htmlString, "text/html", null);
}
}
try this code. If you are learning, use official docs > WebView
String htmlString = "<html><body>Your text.</body></html>";
browser.getSettings().setJavaScriptEnabled(true);
browser.loadData(htmlString, "text/html", null);
Your code working fine. I attached screenshot
Currently I'm trying to figured out which is the best way to invoke javascript from android.
AndroidJSCore. AndroidJSCore
WebView
I've tried AndroidJSCore, it's great. But it would enlarge the apk size.
Then I trying to dive into WebView to invoke javascript. But fail.
Activity look like this:
public class WebViewActivity extends AppCompatActivity {
private WebView webView;
private static final String TAG = WebViewActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
webView = (WebView)findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportZoom(true);
webSettings.setDisplayZoomControls(true);
webView.loadUrl("file:///android_asset/jsWeb/test.html");
webView.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url){
String test1 = "permissionRegist(\"'function'\", [\"'319609831167500021'\",\"'319609831167500022'\",\"'319609831167500023'\",\"'419609839767500020'\",\"'644731700926740003'\",\"'644731700926740004'\",\"'854885785357389824'\",\"'854995673156816896'\",\"'855001385022918656'\",\"'855009454683459584'\",\"'855298661779902464'\",\"'855303143108513792'\",\"'855347061611171840'\",\"'855356859882803200'\"])";
String test2 = "evalJSExpression()";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript(test1, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.d(TAG, s);
}
});
webView.evaluateJavascript(test2, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.d(TAG, s);
}
});
}
}
});
}
}
there appending files are:
android.js
function permissionRegist(type, list) {
var s_permissionMap = new Map();
s_permissionMap.set(type, list);
}
function evalJSExpression() {
var result = 'dddddd';
return result;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LogicalExpression</title>
<!-- 导入script -->
<script type="text/javascript" src="android.js"></script>
</head>
<body>
<!--<button onClick="permissionRegist()">点击读取文件</button>-->
</body>
</html>
but the result is :
I/chromium: [INFO:CONSOLE(2)] "Uncaught ReferenceError: Map is not defined", source: file:///android_asset/jsWeb/android.js (2)
D/WebViewActivity: null
D/WebViewActivity: "dddddd"
Have you tried https://github.com/mozilla/rhino
here is an example : http://lifeofcoding.com/2015/04/05/Execute-JavaScript-in-Android-without-WebView/
AndroidJSCore is a great lib for android to invoke javascript without WebView.
It seems that Both Native WebView and rhino might have some compilable issues due to the different versions of javascript.
Welcome to contact me about this.
I would find out why when I have time.
I need to open new activity and do other functions like display a Toast in native android java , when button in HTML is clicked. I found a similar question and solution with the problem I'm having, but unfortunately the answer doesn't help. Start new Activity when html button clicked in Cordova
Here is the log:
04-13 11:21:00.080: D/WebViewCallback(23907): onConsoleMessage
04-13 11:21:00.080: D/CordovaLog(23907): file:///android_asset/www/index.html: Line 13 : Uncaught ReferenceError: MyJSInterface is not defined
New Log using 'extends CordovaActivity':
04-14 10:21:33.544: W/ResourceType(18650): No package identifier when getting name for resource number 0x00000064
04-14 10:21:33.545: W/ResourceType(18650): No package identifier when getting name for resource number 0x00000064
04-14 10:21:34.229: W/ResourceType(18650): No package identifier when getting name for resource number 0x00000064
04-14 10:21:34.231: I/View(18650): Touch down dispatch to org.apache.cordova.CordovaWebView{41cdc4d8 VFEDH.C. .F...... 0,0-720,1230 #64}, event = MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=52.92649, y[0]=183.81734, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5511466, downTime=5511466, deviceId=4, source=0x1002 }
04-14 10:21:34.372: W/ResourceType(18650): No package identifier when getting name for resource number 0x00000064
04-14 10:21:34.372: I/View(18650): Touch up dispatch to org.apache.cordova.CordovaWebView{41cdc4d8 VFEDH.C. .F...... 0,0-720,1230 #64}, event = MotionEvent { action=ACTION_UP, id[0]=0, x[0]=52.92649, y[0]=183.81734, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5511610, downTime=5511466, deviceId=4, source=0x1002 }
And here is my Java
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import org.apache.cordova.*;
public class MainActivity extends CordovaActivity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.init();
appView.addJavascriptInterface(new MyJSInterface(),
"myJSInterface");
// Set by <content src="index.html" /> in config.xml
loadUrl(launchUrl);
}
//JSInterface class
public class MyJSInterface {
public MyJSInterface() {
// TODO Auto-generated constructor stub
Log.i(TAG, "constructor of jsinterface");
}
public void btnClick() {
//do something
Log.i(TAG, "HELLO");
Toast.makeText(getApplicationContext(), "HELLO", Toast.LENGTH_SHORT).show();
}
}
}
And in my HTML
<!DOCTYPE HTML>
<html>
<head>
<title>PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
</head>
<body>
<h1>Hello PhoneGap</h1>
<button onclick="callFunction()">test</button>
</body>
<script>
function callFunction(){
MyJSInterface.btnClick();
}
</script>
</html>
You should have a look at Cordova plugins, as it provides a standard way of accessing the native functionality of the device. It is preferable to baking in your custom way.
Closer to this topic, it might be that this plugin is exactly what you want.
I've used the code example posted here calling date picker from javascript and this works fine in the android emulator. When I click on the date input box in web view, the android date picker appears and I can select it.
However, when I test this on my device, I just get a standard text input field it is as though the method is not being called. Does anyone have any suggestions? The full code I am using is:
public class MainActivity extends ActionBarActivity {
public WebView mWebView;
#Override
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
final MyJavaScriptInterface myJavaScriptInterface = new MyJavaScriptInterface(this);
mWebView.addJavascriptInterface(myJavaScriptInterface, "MyJavaScriptInterface");
mWebView.loadUrl("http:// mywebsite.html");
}
// Classe de prise en charge du java privé
public class MyJavaScriptInterface {
public String m_szTagId;
Context mContext;
MyJavaScriptInterface(Context c) {
mContext = c;
}
public void openDatePickerDialog(String szTagId) {
m_szTagId = szTagId;
Calendar c = Calendar.getInstance();
DatePickerDialog dp = new DatePickerDialog(mContext, new OnDateSetListener() {
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
String szDate = String.format("%04d/%02d/%02d", year, monthOfYear + 1, dayOfMonth);
mWebView.loadUrl("javascript:callFromActivity_RetDate(\"" + m_szTagId + "\", \"" + szDate + "\")");
}
}, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
dp.show();
}
} // Class MyJavaScriptInterface
#Override
public boolean onCreateOptionsMenu (Menu menu){
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item){
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
and the Javascript code is:
// ---- date picker to call methods of the android device
$('#datepicker').click(function(e){
getDataDate();
});
function getDataDate(){
MSSAndroidFunction.openDatePickerDialog('datepicker');
}
function callFromActivity_RetDate(datepicker, data) {
document.subHours.datepicker.value = data;
}
You have named your JavaScript Interface as MyJavaScriptInterface, so you must call it from JavaScript.
I.e.:
Instead of MSSAndroidFunction.openDatePickerDialog('datepicker'), you must do MyJavaScriptInterface.openDatePickerDialog('datepicker'), in a JavaScript method.
I have a WebView based application, in which I define the Interface in another class, not an inner class, and in the initialization I do:
htmlInterface=new HTMLInterface(this, webView);
webView.addJavascriptInterface(htmlInterface, "Android");
Hope it helps you
Regards