繁体   English   中英

从Xamarin中的C#对象调用JavaScript

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM