I'm wondering if it is possible to call a function from a java json object?
Example
java:
JSONObject json = new JSONObject();
json.put("fnRowCallback", "test()");
jquery:
$ (function () {
"use strict";
function test() {
alert('test');
}
}(jQuery));
Ultimate accomplishment needed.
JSONObject json = new JSONObject();
json.put("fnRowCallback", function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
if (aData["rush"] == "Rush" ) {
$(nRow).addClass("gradeX");
}
});
You can accomplish this if you instead have your Java return javascript.
<script src="myjavapage.jsp"></script>
have your Java return
$(function(){
alert('test');
});
however I can't think of a good reason to code it this way rather than instead having a js file that gets the content on demand using ajax and not including code in your json. It seems pretty pointless.
I ended up answering my own question. The solution is to use a JSONLiteral like so,
Java
public JSONObject getOptions() {
JSONObject json = new JSONObject();
json.put("fnRowCallback", new JSONLiteral(String.format("fnRowCallback()")));
return json;
}
JS.
function fnRowCallback(){
var fnRowCallback = function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
if (aData["rush"] == "Rush" ) {
nRow.className = nRow.className + " gradeX";
}
};
return fnRowCallback;
}
Thanks Everyone.
See Function.prototype.call or Function.prototype.apply
var obj = {
foo: function() {
console.log('foo called');
}
};
var json = {method: "foo"};
obj[json.method].call(this);
Related
I am a novice to Android app development and Firebase.
I want to know how can I get the value (String & Int) in the JSONArray file stored in Firebase Remote Config?
I use Firebase Remote Config with the final goal to compare my app's version code and priority level with the one stored in Firebase Remote Config to determine initiation of App Update notification, but so far I still unable get Remote Config value.
I tried to parse the JSON using Volley (jsonParse in MainActivity2 class), but it also didn't work. (Error bad url)
I have several times tried to implement previous answers, but maybe because of my misunderstanding, all those came to no avail.
Can I declare an array to Firebase Remote config?
Can I get JSONObject from Default value of Firebase Remote Config
FirebaseRemoteConfig getString is empty
I also have read this interesting article about implementing in-app updates notifications with some specific criteria using Remote Config, but unfortunately for me, the codes are written in Kotlin.
https://engineering.q42.nl/android-in-app-updates/
test_json file stored in Firebase Remote Config.
[
{
"versionCode": "1",
"priorityLevel": 2
},
{
"versionCode": "2",
"priorityLevel": 4
},
{
"versionCode": "3",
"priorityLevel": 1
}
]
MainActivity2 class
remoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setFetchTimeoutInSeconds(2000)
.build();
remoteConfig.setConfigSettingsAsync(configSettings);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
remoteConfig.fetchAndActivate().addOnCompleteListener(new OnCompleteListener<Boolean>() {
#Override
public void onComplete(#NonNull Task<Boolean> task) {
if (task.isSuccessful()) {
String object = remoteConfig.getString("test_json");
//jsonParse(object);
Gson gson = new GsonBuilder().create();
ArrayList<Lessons> lessons = gson.fromJson(object,
new TypeToken<List<Lessons>>(){}.getType());
} else {
Toast.makeText(MainActivity2.this, "Fetch Failed!", Toast.LENGTH_SHORT).show();
}
}
});
}
});
private void jsonParse(String object) {
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, object, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("condition");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject condition = jsonArray.getJSONObject(i);
String versionCode = condition.getString("versionCode");
int priorityLevel = condition.getInt("priorityLevel");
textView.append(versionCode + "\n\n");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mQueue.add(request);
}
Lessons class
public class Lessons {
String versionCode;
Int priorityLevel;
}
Any help would be greatly appreciated.
Thank you.
For me worked like that
import com.google.gson.annotations.SerializedName
data class VersionData(
#SerializedName("name")
val name: String,
#SerializedName("age")
var age: Int,
#SerializedName("isFemale")
var isFemale: Boolean
)
init {
remoteConfig.fetchAndActivate()
}
private val _mutableLiveData = MutableLiveData<VersionData>()
val remoteLiveData: LiveData<VersionData> = _mutableLiveData
fun remoteConfiguration() {
val gson = Gson()
val remote = remoteConfig.fetchAndActivate()
remote.addOnSuccessListener{
val stringJson = remoteConfig.getString("json_object_name")
if(stringJson.isNotEmpty()){
val jsonModel = gson.fromJson(stringJson, VersionData::class.java)
_mutableLiveData.value = VersionData(
name = jsonModel.name,
age = jsonModel.age,
isFemale = jsonModel.isFemale
)
}else{
// probably your remote param not exists
}
}
}
so observe in compose
val localLifecycle = LocalLifecycleOwner.current
myViewModel.remoteLiveData.observe(localLifecycle){
Log.d("remoteLiveData", "remoteLiveData: $it")
}
I recommend you use Gson.
data class Lessons(
val versionCode: String? = null,
val priorityLevel: Int? = null
)
and then, use getValue() or getString() to get the data.
val list = Gson().fromJson(getValue("test_json").asString(), Array<Lessons>::class.java)
In my case, getString() also worked.
val list = Gson().fromJson(getString("test_json"), Array<Lessons>::class.java)
This is simpler.
I'm trying to figure aout, why my firestore function is always returning null.
Here is my firestore function:
exports.isUserOnListFunction = functions.https.onCall(async (data, context) => {
const userID = context.auth.uid;
const userEmail = context.auth.token.email;
const atIndex = userEmail.indexOf('#');
const dotIndex = userEmail.indexOf('.');
var userName = userEmail.slice(0, dotIndex);
var userSurname = userEmail.slice(dotIndex+1, atIndex);
userName = capitalizeFirstLetter(userName);
userSurname = capitalizeFirstLetter(userSurname);
return db.collection('allowed_users')
.where("name", "==", userName)
.where("surname", "==", userSurname)
.get().then(snap => {
if (!snap.empty) {
db.collection("users").doc(userID).update({
onList: true
});
return {onList : true};
}
}).catch(()=>{
console.log("Some error!")
})
});
and here is my android (java) function calling firestore function:
private Task<String> isUserOnList(){
return mFunctions
.getHttpsCallable("isUserOnListFunction")
.call()
.continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
String result = (String) task.getResult().getData();
System.out.println(result);
return result;
}
});
}
Could someone please tell me what im doing wrong?
According to this doc
If returned is JS object with keys and values, which I suppose it is in this situation, getData() returns Map object.
I think task.getResult().getData().toString() method should be used to convert it (instead of (String) task.getResult().getData();)
I would expect exception thrown, but maybe you have caught it in other parts of code not posted here.
Hope this will helps you.
I am trying to use Javascript websockets to connect to a Java servlet, but the onError function is always being called, and is not providing much information. My javascript:
var webSocket = new WebSocket('ws://localhost:8080/test');
webSocket.onerror = function(event) {
onError(event);
};
webSocket.onclose = function(event) {
onClose(event);
};
webSocket.onopen = function(event) {
onOpen(event);
};
webSocket.onmessage = function(event) {
onMessage(event);
};
function onClose(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
alert(code + "; " + reason + "; " + wasClean);
}
function onMessage(event) {
//do stuff
}
function onOpen(event) {
webSocket.send('opening socket');
}
function onError(event) {
alert(event.message);
}
For my servlet, I have
#ServerEndpoint("/test")
public class TranscoderSNSServlet extends HttpServlet {
...
}
The only useful error codes I've been able to find are that event.code = 1006, event.wasClean = false. The browser I am using definitely supports websockets. I am trying to run this on ElasticBeanstalk. Any help is appreciated
I am new to Gwt,i m implementing a webclipper project so my task to send some parameters from javascript file to Gwt so that i will be able to make the connection with my couchdb database but i am getting a problem in passing parameters like title, url ,and summary from webpage to Gwt n then couchdb.The following code is my javascript code:-
function onPageInfo(o) {
document.getElementById('title').value = o.title;
document.getElementById('url').value = o.url;
document.getElementById('summary').innerText = o.summary;
}
// Global reference to the status display SPAN
var statusDisplay = null;
// POST the data to the server using XMLHttpRequest
function addBookmark() {
// Cancel the form submit
event.preventDefault();
// The URL to POST our data to
var postUrl = "http://127.0.0.1:8888/practice.html? gwt.codesvr=127.0.0.1:9997&gwt.codesvr=127.0.0.1:9997/?title=1&url=2&summary=3";
// Set up an asynchronous AJAX POST request
var xhr = new XMLHttpRequest();
xhr.open('POST', postUrl, true);
// Prepare the data to be POSTed
var title = encodeURIComponent(document.getElementById('title').value);
var url = encodeURIComponent(document.getElementById('url').value);
var summary = encodeURIComponent(document.getElementById('summary').value);
var tags = encodeURIComponent(document.getElementById('tags').value);
var params = 'title=' + title +
'&url=' + url +
'&summary=' + summary +
'&tags=' + tags;
// Replace any instances of the URLEncoded space char with +
params = params.replace(/%20/g, '+');
// Set correct header for form data
xhr.setRequestHeader('Content-type', 'application/json');
// Handle request state change events
xhr.onreadystatechange = function() {
// If the request completed
if (xhr.readyState == 4) {
statusDisplay.innerHTML = '';
if (xhr.status == 200) {
// If it was a success, close the popup after a short delay
statusDisplay.innerHTML = 'Saved!';
window.setTimeout(window.close, 1000);
} else {// Show what went wrong
statusDisplay.innerHTML = 'Error saving: ' + xhr.statusText;
}
}
};
// Send the request and set status
xhr.send(params);
statusDisplay.innerHTML = 'Saving...';
}
// When the popup HTML has loaded
window.addEventListener('load', function(evt) {
// Handle the bookmark form submit event with our addBookmark function
document.getElementById('addbookmark').addEventListener('submit', addBookmark);
// Cache a reference to the status display SPAN
statusDisplay = document.getElementById('status-display');
// Call the getPageInfo function in the background page, injecting content_script.js
// into the current HTML page and passing in our onPageInfo function as the callback
chrome.extension.getBackgroundPage().getPageInfo(onPageInfo);
});
Thanks.....
You can call a function defined in a java file (of GWT client module) by exporting that function. Let's assume there is a class A.java which is also your entry point class. This class contains someMethod() which you need to call from javascript passing some parameters. The content of your class A would be something like
public class A implements EntryPoint {
public static functionExported = false;
public void onModuleLoad() {
ExportToBeCalledFromJs();
// other code goes here
}
public static native void ExportToBeCalledFromJs() /*-{
$wnd.toBeCalledFromJs = $entry(function(s1, s2) {
return #com.practice.gwt.client.A::someFunction();
});
#com.practice.gwt.client.A:functionExported = true;
}-*/;
}
Above code exports the function and makes it available to javascript. You can simply call toBeCalledFromJs(param1, param2) fromyour js where param1 would substitute s1 and param2 would substitute s2. If you wish to add more parameters you can modify $entry(function(s1, s2) in the code above.
How do we call javascript from Android? I have this javascript library which I would like to use, I want to call the javascript function and pass the result value to the android java code. Haven't found the answer from now. i managed to call android code from javascript, but I want the other way around.
There is a hack:
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectCallback, "JavaCallback")
Force execute javascript within an existing page by
WebView.loadUrl("javascript: var result = window.YourJSLibrary.callSomeFunction();
window.JavaCallback.returnResult(result)");
(in this case your java class JavaObjectCallback should have a method returnResult(..))
Note: this is a security risk - any JS code in this web page could access/call your binded Java object. Best to pass some one-time cookies to loadUrl() and pass them back your Java object to check that it's your code making the call.
You can use Rhino library to execute JavaScript without WebView.
Download Rhino first, unzip it, put the js.jar file under libs folder. It is very small, so you don't need to worry your apk file will be ridiculously large because of this one external jar.
Here is some simple code to execute JavaScript code.
Object[] params = new Object[] { "javaScriptParam" };
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
Context rhino = Context.enter();
// Turn off optimization to make Rhino Android compatible
rhino.setOptimizationLevel(-1);
try {
Scriptable scope = rhino.initStandardObjects();
// Note the forth argument is 1, which means the JavaScript source has
// been compressed to only one line using something like YUI
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
// Get the functionName defined in JavaScriptCode
Object obj = scope.get(functionNameInJavaScriptCode, scope);
if (obj instanceof Function) {
Function jsFunction = (Function) obj;
// Call the function with params
Object jsResult = jsFunction.call(rhino, scope, scope, params);
// Parse the jsResult object to a String
String result = Context.toString(jsResult);
}
} finally {
Context.exit();
}
You can see more details at my post.
In order to match the method calls of the iOS WebviewJavascriptBridge ( https://github.com/marcuswestin/WebViewJavascriptBridge ), I made some proxy for the calls of register_handle and call_handle. Please note I am not a Javascript-guru therefore there is probably a better solution.
javascriptBridge = (function() {
var handlers = {};
return {
init: function () {
},
getHandlers : function() {
return handlers;
},
callHandler : function(name, param) {
if(param !== null && param !== undefined) {
JSInterface[name](param);
} else {
JSInterface[name]();
}
},
registerHandler : function(name, method) {
if(handlers === undefined) {
handlers = {};
}
if(handlers[name] === undefined) {
handlers[name] = method;
}
}
};
}());
This way you can send from Javascript to Java calls that can have a String parameter
javascriptBridge.callHandler("login", JSON.stringify(jsonObj));
calls down to
#JavascriptInterface
public void login(String credentialsJSON)
{
Log.d(getClass().getName(), "Login: " + credentialsJSON);
new Thread(new Runnable() {
public void run() {
Gson gson = new Gson();
LoginObject credentials = gson.fromJson(credentialsJSON, LoginObject.class);
SingletonBus.INSTANCE.getBus().post(new Events.Login.LoginEvent(credentials));
}
}).start();
}
and you can call back to Javascript with
javascriptBridge.registerHandler('successfullAuthentication', function () {
alert('hello');
})
and
private Handler webViewHandler = new Handler(Looper.myLooper());
webViewHandler.post(
new Runnable()
{
public void run()
{
webView.loadUrl("javascript: javascriptBridge.getHandlers().successfullAuthentication();"
}
}
);
If you need to pass a parameter, serialize to JSON string then call StringEscapeUtils.escapeEcmaScript(json), otherwise you get unexpected identifier: source (1) error.
A bit tacky and hacky, but it works. You just have to remove the following.
connectWebViewJavascriptBridge(function(bridge) {
}
EDIT:
in order to change the global variable to an actual property, I changed the above code to the following:
(function(root) {
root.bridge = (function() {
var handlers = {};
return {
init: function () {
},
getHandlers : function() {
return handlers;
},
callHandler : function(name, param) {
if(param !== null && param !== undefined) {
Android[name](param);
} else {
Android[name]();
}
},
registerHandler : function(name, method) {
if(handlers === undefined) {
handlers = {};
}
if(handlers[name] === undefined) {
handlers[name] = method;
}
}
};
}());
})(this);
I got the idea from Javascript global module or global variable .
For a full implementation of JavaScript that doesn't require using a slow WebView, please see AndroidJSCore, which is a full port of Webkit's JavaScriptCore for Android.
UPDATE 2018: AndroidJSCore is deprecated. However, its successor, LiquidCore has all of the same functionality and more.
Calling functions from Android is very simple:
JSContext context = new JSContext();
String script =
"function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
"var fact_a = factorial(a);\n";
context.evaluateScript("var a = 10;");
context.evaluateScript(script);
JSValue fact_a = context.property("fact_a");
System.out.println(df.format(fact_a.toNumber())); // 3628800.0