Exist stringByEvaluatingJavaScriptFromString for Android - javascript

Exist stringByEvaluatingJavaScriptFromString method in Android like Iphone?.
Not with a simple code like this javascript:wave(). But with a complex Java Script function.
Thanks

You can use loadUrl instead,eg:
webView.loadUrl("javascript:PerformSimpleCalculation()");
It's effect similar to stringByEvaluatingJavaScriptFromString.The API description is not clear.

stringByEvaluatingJavaScriptFromString is a private method in Android API. But it is really useful.
You could retrive this API via Java reflection:
Method stringByEvaluatingJavaScriptFromString , sendMessageMethod;;
Object webViewCore , browserFrame;
private boolean hasIntercepted = true;
Object webViewObject = this;
Class webViewClass = WebView.class;
try {
Field mp = webViewClass.getDeclaredField("mProvider");
mp.setAccessible(true);
webViewObject = mp.get(this);
webViewClass = webViewObject.getClass();
Field wc = webViewClass.getDeclaredField("mWebViewCore");
wc.setAccessible(true);
webViewCore = wc.get(webViewObject);
if (webViewCore != null) {
sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);
sendMessageMethod.setAccessible(true);
Field bf= webViewCore.getClass().getDeclaredField("mBrowserFrame");
bf.setAccessible(true);
browserFrame = bf.get(webViewCore);
stringByEvaluatingJavaScriptFromString = browserFrame.getClass().getDeclaredMethod("stringByEvaluatingJavaScriptFromString", String.class);
stringByEvaluatingJavaScriptFromString.setAccessible(true);
}
hasIntercepted = true;
} catch (Throwable e) {
hasIntercepted = false;
}
Then to use this method:
Object argument =(Object) ((String)"window.hitTest("+event.getX()+ ","+event.getY()+")");
try {
Object _tagName = stringByEvaluatingJavaScriptFromString.invoke(browserFrame, argument);
String tagName =(String)_tagName;
} catch (Exception e) {
e.printStackTrace();
}

Related

Unity jslib import in c# script don't work?

I started using jslib plugins with unity and following the documentation I created this jslib file:
var plugin = {
Autologin: function () {
var sessionData = [
sessionStorage.getItem("USERNAME"),
sessionStorage.getItem("PASSWORD")
];
return sessionData;
},
GetTargetParams: function () {
function findGetParameter(parameterName) {
var result = null,
tmp = [];
var items = location.search.substr(1).split("&");
for (var index = 0; index < items.length; index++) {
tmp = items[index].split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
}
return result;
}
return findGetParameter("platform");
},
};
mergeInto(LibraryManager.library, plugin);
I use the jslib functions in the c# file like that:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using System;
using System.Runtime.InteropServices;
public class InitHandler : MonoBehaviour
{
public bool isMobile = false;
[DllImport("__Internal")]
private static extern string[] Autologin();
[DllImport("__Internal")]
private static extern string GetTargetParams();
// Start is called before the first frame update
void Start()
{
try
{
switch (GetTargetParams())
{
case "mobile":
isMobile = true;
break;
case "pc":
isMobile = false;
break;
}
}
catch { Debug.LogWarning("Target checking will not be executed cause it's not a webgl build."); }
try
{
StartCoroutine(StartAUTOLogin(Autologin()[0], Autologin()[1]));
}
catch { Debug.LogWarning("Autologin will not be executed cause it's not a webgl build."); }
SceneManager.LoadScene("Login");
}
// Update is called once per frame
void Update()
{
}
IEnumerator StartAUTOLogin(string User, string Password)
{
WWWForm form = new WWWForm();
form.AddField("Username", User);
form.AddField("Password", Password);
}
}
When I build this i don't get ANY compiler errors. My question is now why the functions I import don't work in a webgl build. So when I pass the parameter platform=mobile it's not setting isMobile to true. I'm beginner with jslibs so don't be hard please and don't critisize my english. I'm not native speaker.
Hope you can help me,
Franz Fischer

Remember Me button in android app

I have recently created a new plugin for an android app I've been working on. This plugin requires the use of a remember me function that I cant seem to get working properly. Within my code I've designated the use of shared properties at the top and the string pass.
View thisScreensView = null;
String errormessage = "";
String errormessageTextColor = "";
String errormessageText = "";
String rememberTextText = "";
String rememberTextTextColor = "";
String voucherTextfieldPlaceholder = "";
String voucherTextfieldSecureTextEntry = "";
boolean voucherTextfieldSecureTextEntryBool = false;
String iphoneImage = "";
String ipadImage = "";
String errormessageInvalid = "";
String errormessageRemember = "";
private TextView errormessageTextView = null;
private EditText voucherTextfieldEditText = null;
private ImageView imageView = null;
private Button submitButton = null;
private Switch rememberSwitch = null;
private Drawable myHeaderImageDrawable = null;
private String alphaImage = "", pass;
private static BT_item screenObjectToLoad = null;
SharedPreferences sharedpreferences;
I have it assigning the variable pass into the designated text box with this code:
voucherTextfieldEditText.setVisibility(View.VISIBLE);
rememberSwitch = (Switch) thisScreensView.findViewById(R.id.rememberSwitch);
// set the switch to ON
rememberSwitch.setText(errormessageRemember);
rememberSwitch.setChecked(true);
// attach a listener to check for changes in state
rememberSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
BT_debugger.showIt(fragmentName + ":rememberSwitch is ON");
// switchStatus.setText("Switch is currently ON");
//voucherTextfieldEditText.setText(pref.getString(pass, null));
} else {
BT_debugger.showIt(fragmentName + ":rememberSwitch is OFF");
// switchStatus.setText("Switch is currently OFF");
}
}
});
// check the current state before we display the screen
if (rememberSwitch.isChecked()) {
BT_debugger.showIt(fragmentName + ":rememberSwitch is ON");
// switchStatus.setText("Switch is currently ON");
//voucherTextfieldEditText.setText(pass);
if (voucherTextfieldEditText!=null) {
//voucherTextfieldEditText.setText(sharedPreferences.getString(pass, ""));
}
if (pass != null) {
String textfield = sharedpreferences.getString("PASS", pass);
//voucherTextfieldEditText.setText(sharedPreferences.getString("PASS", pass));
voucherTextfieldEditText.setText(textfield);
}
}
else {
BT_debugger.showIt(fragmentName + ":rememberSwitch is OFF");
// switchStatus.setText("Switch is currently OFF");
}
//
// submit click listener..
submitButton = (Button) thisScreensView.findViewById(R.id.submitButtonVoucher);
submitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
launchScreen(voucherTextfieldEditText.getText().toString());
}
});
// return the layout file as the view for this screen..
return thisScreensView;
}// onCreateView...
Then I set the shared preferences string "PASS" with this line of code:
if (loadScreenNickname.length() > 1 && !loadScreenNickname.equalsIgnoreCase("none")) {
// before we launch the next screen...
if (!rememberSwitch.isChecked()) {
voucherTextfieldEditText.setText("");
}
if (rememberSwitch.isChecked()){
//voucherTextfieldEditText.setText("");
//editor.putString(pass, voucherTextfieldEditText.getText().toString().trim());
//editor.apply();
pass = voucherTextfieldEditText.getText().toString();
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("PASS", pass);
editor.apply();
}
errormessageTextView.setVisibility(View.GONE);
errormessageTextView.invalidate();
//loadScreenObject(null, thisScreen);
try {
loadScreenWithNickname(loadScreenNickname);
foundIt = 1;
} catch (Exception ex){
Log.e ("eTutorPrism Error", "Caught this exception " + ex);
ex.printStackTrace();
}
break;
}
}
However anything I exit and restart the application, even if the remember me button is checked, it doesn't remember the previous value and the app ends up crashing due to a null. Everything else in the code works except the Remember Me. If anyones got any ideas I could use them?
You are not initializing your sharedPreference. try to initialize it.
SharedPreferences sharedPreferences=getSharedPreferences("myPref",MODE_PRIVATE);

SignalR error Cannot implicitly convert type 'System.Threading.Tasks.Task<object>' to 'string'

I'm trying to call a method from my c# hub class but when I try to return a string from the javascript code I get a System.Threading.Tasks.Task instead of a string. I'm wondering how I can edit the javascript method to return an actual string.
Here's the hub class:
public String getMessage(int id)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
var s = hubContext.Clients.All.getMessage(id);
return s;
}
JavaScript:
chat.client.getMessage = function (id) {
for (i = 0; i < messageArr.length; i++) {
if (messageArr[i].ID == id) {
var s = messageArr[i].ID + messageArr[i].Name + messageArr[i].Content;
window.alert(s);
return s;
}
}
}
SignalR does not support return values from clients to hubs. The task returned by Clients.All will complete when all clients have been called.
If you want return values from clients, you will have to manually call the hub with the correct value and match the caller using your own message id.
See the documentation
You can't get a return value from a client method; syntax such as int
x = Clients.All.add(1,1) does not work.

SignalR Client Methods not firing consistently

I have a simple SignalR proxy with a single client method on it. The javascript looks like the following:
var proxy = $.connection.orderStatusUpdateEmitter;
proxy.client.onOrderUpdated = function(order){
try {
//This is only hit sometimes
getCustomerOrders(userId)
} catch (e) {
}
}
proxy.connection.start().done(function(c){
$log.info('Connected to order status update emitter');
});
proxy.connection.disconnected = function(data){
$log.info('disconnected');
setTimeout(function() {
proxy.connection.start();
},20000);
}
It seems like there is some type of race condition or I am doing this incorrectly because the handler for onOrderUpdated is not consistently hit. Anything glaringly wrong with the implementation above?
There is nothing special happening in my hub on the server, it looks like the following:
[AuthorizeClaims]
public class OrderStatusUpdateEmitter : Hub
{
private static string _groupIdentifier = "OrderStatusUpdate";
public override Task OnConnected()
{
var identity = Context.Request.Environment["user.identity"] as AuthenticatedUserIdentity;
Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
return base.OnConnected();
}
public override Task OnReconnected()
{
var identity = Context.Request.Environment["user.identity"] as AuthenticatedUserIdentity;
Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
return base.OnReconnected();
}
public static string GetGroupIdentifier()
{
return _groupIdentifier;
}
public Order OnOrderUpdate(Order order)
{
Clients.Group(String.Format("{0}-{1}",GetGroupIdentifier(),
order.CustomerId)).onOrderUpdated(obj);
}
}
Try the following instead of Group
list is consisting of users with ',' separator.
string[] group = list.Split(',');
for(int i=0; i < group.length; i++)
Clients.User(group[i]).onOrderUpdated(obj);

WKWebView.EvaluateJavaScript never returns

I'm trying to get a value from my javascript code back to my application using WKWebView.EvaluateJavaScript(string, WKJavascriptEvaluationResult). The problem is, the delegate WKJavascriptEvaluationResult is never called. Here's my code:
C#:
TaskCompletionSource<NSObject> tcs = new TaskCompletionSource<NSObject>();
webView.EvaluateJavaScript(javascript, (result, error) =>
{
tcs.SetResult(result);
});
return tcs.Task.Result;
Javascript:
function a()
{
return "test";
}
a();
The application is stuck on the Wait() call and never returns because the WKJavascriptEvaluationResult never gets called. Is there a know issue that I'm not aware of? Is there a better way to get values from my javascript code to my application, or am I not using it correctly?
Note: I'm using a TaskCompletionSource simply to make the whole method synchronous.
Worked for me in Xamarin Forms should be the same if you are using Xamarin IOS.
public class IosWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>
{
const string HtmlCode = "document.body.outerHTML";
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
WKWebView wKWebView = new WKWebView(Frame, new WKWebViewConfiguration());
wKWebView.NavigationDelegate = new WebViewDelate();
SetNativeControl(wKWebView);
}
if (e.NewElement != null)
{
NSUrlRequest nSUrlRequest = new NSUrlRequest(new NSUrl(hybridWebView.Uri.ToString()));
Control.LoadRequest(nSUrlRequest);
}
}
class WebViewDelate : WKNavigationDelegate
{
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
WKJavascriptEvaluationResult handler = (NSObject result, NSError error) => {
if (error != null)
{
Console.WriteLine(result.ToString());
}
};
webView.EvaluateJavaScript(HtmlCode, handler);
}
}
}
Why don't you use method EvaluateJavaScriptAsync instead of EvaluateJavaScript? I think it leads to much better readability of code - and it might even uses a TaskCompletionSource under the hood :)
try
{
var obj = await Control.EvaluateJavaScriptAsync(js).ConfigureAwait(true);
if (obj != null)
response = obj.ToString();
}
catch (Exception) { /* The Webview might not be ready... */ }

Categories

Resources