I'm making an Android app using webview.
The app can print out receipts. What I want to do is when the printer is not working, alert box shows up to tell the printer isn't working, and return false to the form's onsubmit event to prevent form from being submitted.
Java code:
public class JSKicker {
#JavascriptInterface
public void callPrint(final String argumet) {
Thread thread = new Thread(new Runnable() {
public void run() {
int nRtn;
connectionNum = myPrinter.Connect("000.000.0.000");
if(connectionNum < 0){ //Printer not working
webview.post(new Runnable() {
#Override
public void run() {
String script = "alert('Printer Error'); return printer_connection = false;";
webview.evaluateJavascript(script, new ValueCallback<String>() {
#Override
// I can't figure out what to do here...
});
}
});
}else{ //Printer is working properly
connectionNum = myPrinter.SetLocale(8);
strText = argument;
nRtn = myPrinter.PrintText(strText, "SJIS");
nRtn = myPrinter.PaperFeed(64);
nRtn = myPrinter.CutPaper(1);
myPrinter.Disconnect();
}
}
});
thread.start();
}
JavaScript in header:
<script type="text/javascript">
function gate(){
jQuery.ajax({
url:'/cart_info.php',
type:'GET'
})
.done( (data) => {
window.JSKicker.callPrint(data);
})
if (printer_connection = false) {
return false;
}else{
return true;
}
}
</script>
HTML form tag:
<form method="post" id="order_form" onsubmit="return gate();">
How can I get this work?
Could you do it thru WebView.evaluateJavascript()?
https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
So with that you could send simple CustomEvent to document in WebView
webView.evaluateJavascript("document.dispatchEvent(new Event('printer_error', { details: "No printer found!" }));");
and in JavaScript you can hook listener for your custom event to react.
document.addEventListener('printer_error', e => alert(e.details));
Didn't test this so might be that at least evaluateJavascript() needs callback function.
WebSocket can solve your problem.
WebSockets provide a persistent connection between a client and server that both parties can use to start sending data at any time. The client establishes a WebSocket connection through a process known as the WebSocket handshake.
Its very straight forward and easy to implement.
You can follow referrer links for more details:-
JAVA WebSocket:- WebSocket using Spring Boot, WebSocket using Simple JEE
Browser WebSocket(JavaScript):- WebSocket API
In Android ,if you want webview pass value to JavaScript.
First,you need to set the webview enable the JavaScript,
private WebView mWebView;
void onCreate(){
mWebView = findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
}
And ,in you want do some thing code
if(connectionNum < 0){ //Printer not working
// I need to do something here to send a message that the printer isn't working to JS.
//In thread can not use mWebView,should send message to MainThread to do
// mWebView.loadUrl("javascript:javaCall()");
Message msg = new Message();
msg.what = 1;
myHandler.sendMessage(msg);
//myHandler can be your MainThread send to here
}
And where the mWebView created in your code, be in main thread ,you can use the
Handler to deal with the message sended to here.
private Handler myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// this 1 is just thread send to here
if (msg.what == 1) {
//and here can do the webview UI method
mWebView.loadUrl("javascript:javaCall()");
}
}
};
the javaCall() is where you JacaScript invoke method,in javaScript you can writre like this:
<script language="javascript">
function javaCall(){
alert("Printer Error");
//other thing you can do
}
</script>
if you have problem ,you can refer to the official document.
public void loadUrl (String url)
Loads the given URL.
Also see compatibility note on evaluateJavascript(String, ValueCallback).
webview use link
Related
I have written a code in c#, javascript, using client library SignalR to refresh a page in database value change. My code is
<form asp-action="Start" method="post" class="form-stacked">
<button type="submit" id="startPractice" class="button-primary">Start Practice</button>
</form>
<script src="~/js/ignalr/dist/browser/signalr.js"></script>
<script src="~/js/chat.js"></script>
My API method is which is called while clicking start practice is
public async Task<IActionResult> Index(long sessionId)
{
// Database change logic
SignalRClientHub sr = new SignalRClientHub();
await sr.SendMessage();
// Rest of the logic
return this.View();
}
public class SignalRClientHub : Hub
{
public async Task SendMessage(string user = null, string message = null)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
code of chat.js
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/SignalRClient").build();
connection.on("ReceiveMessage", function (user, message) {
location.reload();
});
When I click the button start practice it hits SendMessage Method, but I got an error
object reference not set to an instance
because the value of the Client was null. How Can I fix this?
You cannot new up a hub manually. In order to send to clients from outside of the hub you need to use the IHubContext<THub>. See the docs for details https://learn.microsoft.com/aspnet/core/signalr/hubcontext?view=aspnetcore-5.0
How to scrape 'handlerbars.js' javascript template in htmlunit 2.21? I try to execute this, but this message shown:
'text/x-javascript-template' is not javascript.
and script does not execute. I execute command page.asXml().
Output text is nothing. Do you know dependency for execute javascript template in Htmlunit? Please help.
This Code
HtmlUnit Config
webClient = new WebClient(BrowserVersion.CHROME);
webClient.getBrowserVersion().setBrowserLanguage("ko-kr");
ConfirmHandler okHandler = new ConfirmHandler() {
#Override
public boolean handleConfirm(Page page, String message) {
logger.info("[Confirm] " + message);
return true;
}
};
AlertHandler alertHandler = new AlertHandler() {
#Override
public void handleAlert(Page page, String message) {
logger.info("[Alert] " + message);
}
};
webClient.setRefreshHandler(new ImmediateRefreshHandler());
webClient.getOptions().setGeolocationEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setUseInsecureSSL(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(script);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(0);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.setConfirmHandler(okHandler);
webClient.setAlertHandler(alertHandler);
page move code
page = webClient.getPage("https://promotions.expediapartnercentral.com/promotions/manageroomandrate.html?htid=" + siteIdx);
webClient.waitForBackgroundJavaScript(1000);
page.asXml() repsonse is empty(script is not execute)
I have setup a page so that when a link is clicked it calls a JavaScript function which calls a Page Method. This works perfectly on our development and staging sites but does not work on our live site. There is no error being generated, it just doesn't call the method. I do have the script manager tag on the page and "EnablePageMethods" is set to true. Does anyone have any ideas. Thank you in advance for any help that maybe offered.
<script type='text/javascript'>
function RequestAQuote_Click(ctti) {
PageMethods.RecordClickThrough(ctti);
}
</script>
[WebMethod]
public static void RecordClickThrough(int clickThroughTrackedId)
{
try
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["globalair"].ToString()))
{
connection.Open();
using (SqlCommand command = new SqlCommand("seo.spRecordClickThroughs", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.AddWithValue("#ClickThroughsTrackedId", clickThroughTrackedId);
command.ExecuteNonQuery();
}
}
}
catch(Exception ex)
{
ErrorLog(ex.ToString(), "RecordClickThrough");
}
}
I am writing to seek help, in regards creating a real-time data update using SignalR. I am currently having issue on the client-side, where I am unable to render the data content.
I have a tested the query command and it seems to be returning data. This leads me to believe, that my client-side code, maybe incorrect.
<script src="~/Scripts/jquery-1.8.2.min.js" type="text/javascript" ></script>
<script src="~/Scripts/jquery.signalR-2.0.1.min.js" type="text/javascript" ></script>
<script src="~/signalr/hubs" type="text/javascript" ></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.NotificationHub;
// Create a function that the hub can call to broadcast messages.
notifications.client.recieveNotification = function (role, descrip) {
// Add the message to the page.
$('#spanNewMessages').text(role);
$('#spanNewCircles').text(descrip);
};
// Start the connection.
$.connection.hub.start().done(function () {
notifications.server.sendNotifications(function () {
alert("does it work");
});
}).fail(function (e) {
alert(e);
});
</script>
<h1>New Notifications</h1>
<div>
<b>New <span id="spanNewMessages"></span> role.</b><br />
<b>New<span id="spanNewCircles"></span> descrip.</b><br />
</div>
Hub Class:
[HubName("NotificationHub")]
public class notificationHub : Hub
{
string role = "";
string descrip = "";
[HubMethodName("sendNotifications")]
public void SendNotifications()
{
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["dummyConnectionString"].ConnectionString))
{
string query = "SELECT [role],[description] FROM [dbo].[User]";
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
role = dt.Rows[0]["role"].ToString();
descrip = dt.Rows[0]["description"].ToString();
}
}
}
Clients.All.RecieveNotification(role, descrip);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
notificationHub nHub = new notificationHub();
nHub.SendNotifications();
}
}
}
StartUp CLass:
using Microsoft.Owin;
using Owin;
using WebApplication2;
namespace WebApplication2
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Could anyone, please provide some assistant, to where I may be going wrong with this task. Thank you.
I mocked up your app. Your issue was you are returning a string from your hub action:
public string SendNotifications()
{
return context.Clients.All.RecieveNotification(role, descrip);
}
this should be void (you aren't returning anything, but actually calling the clients), and you also don't need to use GlobalHost to get the context here, only when the context isn't available (I.E. calling the hub from the server). Try making these changes:
[HubMethodName("sendNotifications")]
public void SendNotifications()
{
//using...
//IHubContext context = GlobalHost.ConnectionManager.GetHubContext<notificationHub>();
//return context.Clients.All.RecieveNotification(role, descrip);
Clients.All.RecieveNotification(role, descrip);
}
Put a breakpoint at Clients.All... and see if it is being triggered. Let me know if these updates fix your issue.
I am trying to load data into android webview using
webview.loadDataWithBaseURL("", htmlcontent, "text/html", null, "");
a method returns htmlContent from a StringBuilder which populates html data.
I have enabled javascript and set webChromeClient as follows
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(new JSClass(), "Android");
my interface to javascript:
class JSClass {
public void getHTMLContent(String html)
{
Log.i(Global.TAG, "HTMLContentReceived: "+html);
}
}
and my javascript in html page:
<script type="text/javascript">
var ele = document.getElementsByClassName('test');
for(var i=0;i<ele.length;i++){
ele[i].onclick = function(){
window.Android.getHTMLContent(this.innerHTML);
}
}
</script>
but somehow the javascript is not returning any value.
It works fine with loadData(url) where url is a simple webpage in assets folder
Please help
Thanks in advance
You don't have any baseURL to use, since you're loading a dynamical generated HTML.
For this reason webview.loadData(htmlcontent, "text/html", null); should be more than enough.
Javascripts don't throw any exceptions in Java code. Remember that JS is not that type-safe/strict as Java code ... My way of doing is to put logs between sensitive Javascript calls to see if that line passes and to check values. Since you didn't provide the HTML, I would setup the WebChomeClient and override the onConsoleMessage:
webview.setWebChromeClient(new MyChromeClient());
private class MyChromeClient extends WebChromeClient {
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message = consoleMessage.message() + " -- line " + consoleMessage.lineNumber();
switch (consoleMessage.messageLevel()) {
case ERROR:
logErrorMessage(message);
break;
default:
logInfoMessage(message);
break;
}
return true;
}
private void logInfoMessage(String message) {
Log.i("JSTag", message);
}
private void logErrorMessage(String message) {
Log.e("JSTag", message);
}
}
From your JavaScript you would then call for example: console.log('check my value:' + (ele != null)). More info on this here.
Looking at your JavaScript code, I can't understand to what points this.innerHTML.