我正在使用Xamarin框架对HTML5应用程序进行原型设计。我正在尝试将javascript连接到C#代码,反之亦然。
最好的方法是什么?到目前为止,我已经尝试为Cordova框架创建Mono C#绑定,这不是一个理想的解决方案,我正在寻找更直接的东西,利用常见的.Net中心方法。所以我尝试设置一个HttpListener来处理来自javacript调用的app http请求。这种方法适用于Monotouch,但不适用于Mono for Android
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异常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
由于 井架
答案 0 :(得分: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);
}
}
}
答案 1 :(得分:0)
在Android中,localhost IP(运行仿真的计算机的IP)不是127.0.0.1
它的10.0.2.2 ref 可能是也可能不是您错误的来源。
答案 2 :(得分:0)
对任何感兴趣的人 - 我能够在没有
的情况下运行初始代码示例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。
我们使用 Mono 与 WebKit.NET Mac 和 Windows 共享相同代码库的跨平台桌面HTML应用>和 Monobjc 作为 WebKit webview控件。完全免费的工具集btw,包括适用于Mac的InApps(是的Miguel,999美元/平台对于大多数人来说太过分了,包括我自己;)从那个应用程序上的工作我知道只有像
.EvaluateJavaScript(..)
需要在主(也称为UI)线程(以及当然所有UI内容)上调用,因此不确定为什么在问题的代码示例中使用了 RunOnUiThread 。
希望能帮助某人:)