【问题标题】:Monotouch / Mono for Android Javascript to C#Monotouch/Mono for Android Javascript 到 C#
【发布时间】:2013-05-31 04:14:31
【问题描述】:

我正在使用 Xamarin 框架对 HTML5 应用程序进行原型设计。我正在尝试将 javascript 连接到 C# 代码,反之亦然。

最好的方法是什么?到目前为止,我已经尝试创建与 Cordova 框架的 Mono C# 绑定,这不是一个理想的解决方案,我正在寻找更直接的方法来利用常见的以 .Net 为中心的方法。所以我尝试设置一个 HttpListener 来处理来自 javacript 调用的应用程序 http 请求。此方法适用于 Monotouch,但不适用于 Android 的 Mono

Javascript 调用:

<script type="text/javascript">
    function myFunction()
    {
        var request = new XMLHttpRequest();
        request.open('GET','http://127.0.0.1:8001/callnative', false);
        request.send();

        if(request.status == 200){
            alert("Callback!");
        }
        else{
            alert("Error");
        }
    }
</script>

这是 Activity 类中的 C# 代码:

[Activity (Label = "AnroidHTML5Prototype", MainLauncher = true)]
    public class Activity1 : Activity
    {
        int count = 1;

        public HttpListener listener;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SetupListener ();

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button> (Resource.Id.myButton);

            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", count++);
            };

            LoadWebView ();
        }

        private void LoadWebView()
        {
            string lfn = "index.html";
            string html = string.Empty;

            // context could be ApplicationContext, Activity or
            // any other object of type Context
            using (var input = this.ApplicationContext.Assets.Open(lfn))
                using (StreamReader sr = new System.IO.StreamReader(input))
            {
                html = sr.ReadToEnd();
            }

            WebView webView = FindViewById<WebView> (Resource.Id.webView1);
            webView.SetWebChromeClient(new WebChromeClient());
            webView.Settings.JavaScriptEnabled = true;
            webView.LoadData (html, "text/html", null);
            webView.Settings.AllowFileAccess = true;
            webView.Settings.BlockNetworkLoads = false;
        }

        private void SetupListener() {
            listener = new HttpListener();
            listener.Prefixes.Add("http://*:8001/");
            listener.Start();

            listener.BeginGetContext(new AsyncCallback(HandleRequest), listener);
        }

        public void HandleRequest (IAsyncResult result)
        {
            RunOnUiThread(delegate{

                //Get the listener context
                HttpListenerContext context = listener.EndGetContext(result);

                //Start listening for the next request
                listener.BeginGetContext(new AsyncCallback(HandleRequest), listener);

                string response = String.Empty;

                if (context.Request.Url.ToString ().Contains ("callnative")) {
                    response = "native code reply";
                }

                byte[] responseBytes = System.Text.Encoding.UTF8.GetBytes(response);

                context.Response.ContentType = "text/json";
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                context.Response.ContentLength64 = responseBytes.Length;
                context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
                context.Response.OutputStream.Close();


//          WebView webView = FindViewById<WebView> (Resource.Id.webView1);
//          webView.LoadUrl("javascript:(function() { " +  
//                          "alert('Callback!'); " +  
//                          "})()"); 

            });
        }
    }

类似的代码在 Monotouch 中运行良好,但在 Mono for Android 中,我收到以下错误: [Web 控制台] XMLHttpRequest 无法加载 http://127.0.0.1:8001/callnative。无法从 null 发出任何请求。:1 [Web 控制台] 未捕获的错误:NETWORK_ERR: XMLHttpRequest Exception 101:1

我认为这与 Chrome 浏览器文件权限有关,因此我将 WebView 上的 AllowFileAccess 设置设置为 true,但仍然出现相同的错误。

有没有更好的方法在 Mono 中实现 javascript 和 C# 之间的桥梁,或者让 HTTPListener 代码与 Android 一起使用?

这篇文章出现在 Xamarin 文档搜​​索中,但是是 404:

http://docs.xamarin.com/recipes/android/controls/webview/call_c#_from_javascript

谢谢 井架

【问题讨论】:

标签: javascript xamarin.ios xamarin httplistener


【解决方案1】:

通过扩展 WebViewClient 并覆盖 ShouldOverrideUrlLoading 方法,我能够在 Mono for Android 中连接 JS 和 C#:

活动类:

using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Webkit;
using System.IO;
using System.Net;
using System.Text;

namespace AnroidHTML5Prototype
{
    [Activity (Label = "AnroidHTML5Prototype", MainLauncher = true)]
    public class Activity1 : Activity
    {
        protected override void OnCreate (Bundle bundle)
        {
            WebView webView = new WebView (this);
            webView.Settings.JavaScriptEnabled = true;
            webView.SetWebChromeClient(new WebChromeClient());
            string html = "<html><head><title></title></head><body><h1 id='button'>Hello Android</h1><h1 id='message' style='color:red'></h1><script>document.getElementById('button').onclick=function(){window.location='/callnative';}; function callback(msg){document.getElementById('message').innerHTML = msg;}</script></body></html>";
            webView.LoadData (html, "text/html", null);
            webView.SetWebViewClient (new MyWebViewClient(webView));

            base.OnCreate (bundle);
            SetContentView (webView);
        }
    }
}

扩展的 WebViewClient 类:

using System;
using Android.Webkit;
using Java.IO;
using Java.Net;

namespace AnroidHTML5Prototype
{
    public class MyWebViewClient : WebViewClient
    { 
        WebView webView;
        public MyWebViewClient (WebView webView) : base()
        {
            this.webView = webView;
        }

        public override bool ShouldOverrideUrlLoading (WebView view, string url)
        {
            if (url == "/callnative") 
            {
                webView.LoadUrl ("javascript:callback('Hello from Android Native');");
                return true;
            }

            return base.ShouldOverrideUrlLoading(view, url);
        }
    }
}

【讨论】:

    【解决方案2】:

    在 Android 中,本地主机 IP(运行仿真的计算机的 IP)不是 127.0.0.1

    它是 10.0.2.2 ref 这可能是也可能不是您的错误的根源。

    【讨论】:

      【解决方案3】:

      致任何感兴趣的人 - 我能够在没有

      的情况下运行初始代码示例
      RunOnUiThread(delegate{
      

      在我的 html 文件中我也使用了 jQuery AJAX 调用

      <script type="text/javascript" src="../../js/jquery-1.9.1.js"></script>
           ...
      <script type="text/javascript">
          $(document).ready(function () {
              $('#example-1').click(function () {
                  $.ajax({
                      async: true,
                      url: 'http://localhost:8801/test/url/test.htm'
                  });
                  $(this).load('ProgressDialog.htm');
              });
          });
      </script>  
      

      您可能还注意到,使用 localhost 而不是 127.0.0.1,因此基本上相同的代码适用于 Xamarin.iOS 和 Xamarin.Android。

      我们使用 MonoWebKit.NETMacWindows 开发了跨平台桌面 HTML 应用程序,该应用程序共享相同的代码库> 和 Monobjc 作为 WebKit webview 控件。顺便说一句,完全免费的工具集,包括适用于 Mac 的 InApps(是的 Miguel,每个平台 999 美元对于包括我自己在内的大多数人来说太贵了>

      .EvaluateJavaScript(..)
      

      需要在主(又名 UI)线程(当然还有所有 UI 的东西)上调用,所以不确定您为什么在问题的代码示例中使用 RunOnUiThread

      希望对某人有所帮助:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-03
        • 1970-01-01
        • 1970-01-01
        • 2012-10-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多