![](/img/trans.png)
[英]Call C# Function From Javascript in Android Xamarin CrossWalk Webview
[英]Call JavaScript from C# object in Xamarin
我已经能够从MainActivity
C#调用JavaScript,但是我试图从一个对象中调用JavaScript。 我的大部分应用程序都在WebView内运行,我的JavaScript调用C#接口调用一个异步函数,当它完成后,我想回调我的JavaScript,但无法这样做。 这是我当前的设置:在MainActivity
我这样设置WebView:
browser = FindViewById<WebView>(Resource.Id.mainView);
browser.SetInitialScale(1);
browser.SetWebChromeClient(new GeoWebChromeClient());
browser.Settings.UseWideViewPort = true;
browser.Settings.LoadWithOverviewMode = true;
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
WebView.SetWebContentsDebuggingEnabled(true);
}
browser.Settings.SetGeolocationEnabled(true);
browser.Settings.JavaScriptEnabled = true;
browser.AddJavascriptInterface(new JSCSMedium(this, ref browser), "Android");
browser.LoadUrl("file:///android_asset/web/index.html");
然后在JSCSMedium对象中,我有一个asynch函数:
[Export]
[JavascriptInterface]
public void SyncApps()
{
Task t = Task.Run(() => {
IList<ApplicationInfo> tempApps = Application.Context.PackageManager.GetInstalledApplications(PackageInfoFlags.MatchDirectBootAware);
string packageName = "";
string appName = "";
for (int i = 0; i < tempApps.Count(); i++)
{
packageName = tempApps[i].PackageName;
appName = tempApps[i].LoadLabel(manager);
var root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(root, "system");
filePath = System.IO.Path.Combine(filePath, packageName);
if (!System.IO.Directory.Exists(filePath))
{
System.IO.Directory.CreateDirectory(filePath);
}
filePath = System.IO.Path.Combine(filePath, "icon.png");
if (!System.IO.File.Exists(filePath))
{
Drawable icon = tempApps[i].LoadIcon(Application.Context.PackageManager);
BitmapDrawable bd = (BitmapDrawable)icon;
CreateAppIcon(bd.Bitmap, packageName);
}
Intent intent = Application.Context.PackageManager.GetLaunchIntentForPackage(packageName);
if (intent != null)
{
apps.Add(tempApps[i]);
}
}
});
}
如果我不使用C#作为异步函数,它将运行并返回数据,但是此过程会花费一些时间并暂时阻止应用程序。 在MainActivity
内部,我可以使用以下方法调用JavaScript:
browser.EvaluateJavascript("javascript: alert('fooBar');", null);
但是在JSCSMedium
内部无法访问browser
。 我尝试将browser
对象作为参考传递,但通常会引发异常,指出必须在与实例化位置相同的线程上调用EvaluateJavascript
函数。 我也尝试过将我的MainActivity
的引用发送到JSCSMedium
并在MainActivity
调用一个函数来运行EvaluateJavascript
但它似乎无能为力。 没有错误,没有崩溃,什么也没有。
问题是Task.Run
强制代码在线程池中运行,而browser.EvaluateJavascript
Task.Run
需要在主线程上运行。
根据您的需要,这里至少有两个选择:
1)运行Task.Run
块中的EvaluateJavascript调用,如下所示:
var h = new Handler(Looper.MainLooper);
h.Post(() => browser.EvaluateJavascript("javascript: alert('fooBar');", null));
2)在Task.Run
块外部运行EvaluateJavascript调用:
[Export]
[JavascriptInterface]
public async void SyncApps()
{
await Task.Run(() => {
//...
});
browser.EvaluateJavascript("javascript: alert('fooBar');", null);
}
不确定是否可以更改SyncApps()
的返回类型。 如果JS不抱怨,您最好也进行更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.