Forcing Form toolButton click with Javascript

0
0

I’m developing a Xamarin.Forms container as a hybrid app for WiseJ. I want to intercept the hardware back button on Android, and inject javascript to close the active form if possible. I’m not using deep-linking so a simple Browser.GoBack() will not work currently.  My app uses a back button as a Tool component in the form to call custom code.

I can inject Javascript into the window so I was thinking of calling a webmethod in Program.vb to

1) Find the active Form

2) Call the back button code on that form

I was thinking something like this

<WebMethod>
Public Function HitCurrentFormBackButtonIfPossible() As Boolean
Dim intMax As Integer = Application.OpenForms.Count
Dim CurrentForm As Form = Application.OpenForms(intMax – 1) ‘assumes last object in OpenForms is the topmost.
CurrentForm.DialogResult = DialogResult.Cancel
CurrentForm.Close()
End Function

 

Most of these forms simply set a DialogResult = Cancel and close. Problem is, some of these forms have custom code in the back button handler. Do I need to create a custom form class with a BackButton() method and override it on each form?

 

thanks

 

  • You must to post comments
0
0

No, I never solved the problem of the null result.  I can invoke the WebMethod but not get its return result value.

Other than that, it’s completely integrated into Xamarin.  I previously offered to open the source for my Xamarin shell, but now it looks like you guys want to do Android studio and make it cost extra????

–Andrew

 

— event handler for Xamarin

protected override bool OnBackButtonPressed()
{
MessagingCenter.Send<object>(this, “GoBack”);
return true;
}

 

— custom renderer event for Android

protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);

if (Control == null)
{
var webView = new Android.Webkit.WebView(mContext);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JavascriptWebViewClient($”javascript: {JavascriptFunction}”));
SetNativeControl(webView);

MessagingCenter.Subscribe<object>(this, “GoBack”, (sender) => {
webView.EvaluateJavascript(“App.HitFormBackButtonIfPossible(function(result) { });”, new BackButtonAttemptCallback()); //handle the back button behavior we want in WiseJ.
});

 

 

BackButtonAttemptCallBack.cs

 

class BackButtonAttemptCallback : Java.Lang.Object, IValueCallback
{

/// <summary>
/// Here we are trying to get a callback from a WiseJ WebMethod, but its not working. result is always null.
/// https://wisej.com/support/question/forcing-form-toolbutton-click-with-javascript#sabai-entity-content-9216
/// </summary>
/// <param name=”result”></param>
public void OnReceiveValue(Java.Lang.Object result)
{
if (result.ToString() == “False”)
{

JavaSystem.Exit(0); //exit on 2nd backbutton attempt
}
}
}

 

  • You must to post comments
0
0

So I figured that I needed a javascript callback to get the return value of a webmethod when it is called from the browser:

App.Hello(“Jack”, function(result){ alert(result); });

 

So I thought I could use that callback from Xamarin.Forms:

webView.EvaluateJavascript(“App.HitFormBackButtonIfPossible();”, new BackButtonAttemptCallback()); //handle the back button behavior we want in WiseJ.

(this successfully calls the WiseJ webmethod.)

And I’ve implemented a javascript value callback that does trigger:

class BackButtonAttemptCallback : Java.Lang.Object, IValueCallback
{
public void OnReceiveValue(Java.Lang.Object result)
{
if (result.ToString() == “False”) {

JavaSystem.Exit(0);
}
}

However, result is always null.  Any idea what’s going on?

 

  • You must to post comments
0
0

OK, two things. First, I had to update the function to not crash when OpenForms.Count was zero.

Second, when I execute App.HitBackButtonIfPossible() in the Chrome dev console, it returns undefined. Shouldn’t it be returning true or false? I need to get a result back to the Xamarin app so it knows when there are no open forms, and to tell Xamarin to exit the app.  Since we are intercepting the back button in Xamarin, it will not exit the app that way unless we tell it to.

Thanks!

 

 

<WebMethod>
Public Shared Function HitFormBackButtonIfPossible()

Dim intMax As Integer = Application.OpenForms.Count
If (intMax > 0) AndAlso (Application.OpenForms(intMax – 1) IsNot Nothing) Then
Dim intCurrentForm As Form = Application.OpenForms(intMax – 1)

‘See if this form has a method called RequestFormClose()
Dim mi As Reflection.MethodInfo = intCurrentForm.GetType().GetMethod(“RequestFormClose”)
If mi IsNot Nothing Then
‘Form has that method. Call it, and let the form handle it.
CallByName(intCurrentForm, “RequestFormClose”, CallType.Method)
Else
‘Form does not contain that method. We will close the form ourselves.
intCurrentForm.DialogResult = DialogResult.Cancel
intCurrentForm.Close()
End If
Return True ‘Indicate a close request was sent/handled
Else
Return False ‘No form found.
End If
End Function

  • Andrew Niese
    I guess you can only get the result with a callback: App.Hello(“Jack”, function(result){ alert(result); });
  • You must to post comments
0
0

Levi, took a long break from the problem but I think I just got it working.

Instead of creating an inherited form class, I refactored all the back-button code in each form to a new method called RequestFormClose().  Any time a form needs extra processing before closing, we handle it there and always use that name.

In Program.vb’s WebMethod, we get the topmost form, then use Reflection to see if it contains that method (RequestFormClose).  If the form does contain the method, we use CallByName() to invoke it, letting the form handle the close code.  Otherwise, we simply close it.

All that needs to happen in the Xamarin shell now is to call App.HitFormBackButtonIfPossible() when they hit the Android hardware back-button.

Hope this helps other people.

https://pastebin.com/wh5uVNqG

  • You must to post comments
0
0

Hi Andrew,

Did you solve this problem? Using a custom form class would make sense as a reasonable way to solve this issue if you have custom code that interferes with the default back/cancel/close event.

Please share how you proceeded with this!

Best,

Levie

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.