c# –Mono for Android,WebView输入字段filechooser不起作用

c# –Mono for Android,WebView输入字段filechooser不起作用,第1张

概述我有用于上传文件的网页.用户使用<inputtype=“file”/>选择文件并按下提交按钮,一切正常.现在我需要创建Android应用程序(在C#withmonoforandroid),它包含简单的webview,并且必须像web版本一样工作.但我偶然发现了这个问题–当我点击选择文件按钮时,文件对话框无法打开.

我有用于上传文件的网页.用户使用< input type =“file”/>选择文件并按下提交按钮,一切正常.现在我需要创建Android应用程序(在C#with mono for androID),它包含简单的webvIEw,并且必须像web版本一样工作.

但我偶然发现了这个问题 – 当我点击选择文件按钮时,文件对话框无法打开.

几天我用Google搜索了这个问题,但我没有找到任何解决方案.看起来有workaround on Java platform,但它不适用于C#.

有人有任何想法如何让它工作?

解决方法:

我知道如何使它工作.它的一部分是沼泽标准的“如何绑定虚拟方法”,其中一部分是纯粹的无懈可击的邪恶.

首先,我们需要一个“中间人”.由于WebChromeClIEnt未声明openfileChooser()方法,因此我们需要声明一个名为OpenfileWebChromeClIEnt的版本.它声明了一个虚拟的OpenfileChooser方法,并为它提供了一个绑定,以便可以覆盖它:

using System;using AndroID.App;using AndroID.Content;using AndroID.Runtime;using AndroID.OS;using AndroID.Webkit;namespace Scratch.fileUpload{    [Register ("androID/webkit/WebChromeClIEnt", DoNotGenerateAcw=true)]    class OpenfileWebChromeClIEnt : WebChromeClIEnt {        static IntPtr ID_openfileChooser;        [Register ("openfileChooser", "(LandroID/webkit/ValueCallback;)V", "GetopenfileChooserHandler")]        public virtual voID OpenfileChooser (IValueCallback uploadMsg)        {            if (ID_openfileChooser == IntPtr.Zero)                ID_openfileChooser = jnienv.getmethodID (ThresholdClass, "openfileChooser", "(LandroID/webkit/ValueCallback;)V");            if (GetType () == ThresholdType)                jnienv.CallVoIDMethod  (Handle, ID_openfileChooser, new JValue (jnienv.ToJniHandle (uploadMsg)));            else                jnienv.CallNonvirtualVoIDMethod  (Handle, ThresholdClass, ID_openfileChooser, new JValue (jnienv.ToJniHandle (uploadMsg)));        }#pragma warning disable 0169        static Delegate cb_openfileChooser;        static Delegate GetopenfileChooserHandler ()        {            if (cb_openfileChooser == null)                cb_openfileChooser = JNINativeWrapper.CreateDelegate ((Action<IntPtr, IntPtr, IntPtr>) n_OpenfileChooser);            return cb_openfileChooser;        }        static voID n_OpenfileChooser (IntPtr jnienv, IntPtr native__this, IntPtr native_uploadMsg)        {            OpenfileWebChromeClIEnt __this = java.lang.Object.Getobject<OpenfileWebChromeClIEnt> (native__this, JniHandleOwnership.DoNottransfer);            var uploadMsg = java.lang.Object.Getobject<IValueCallback> (native_uploadMsg, JniHandleOwnership.DoNottransfer);            __this.OpenfileChooser (uploadMsg);        }#pragma warning restore 0169    }}

接下来,由于C#缺少匿名内部类,我们需要一个名为MyOpenfileWebChromeClIEnt的显式类:

namespace Scratch.fileUpload {    class MyOpenfileWebChromeClIEnt : OpenfileWebChromeClIEnt {        Action<IValueCallback> cb;        public MyOpenfileWebChromeClIEnt(Action<IValueCallback> cb)        {            this.cb = cb;        }        public overrIDe voID OpenfileChooser (IValueCallback uploadMsg)        {            cb (uploadMsg);        }    }

Activity端口与您引用的博客文章相同,只是它使用MyOpenfileWebChromeClIEnt而不是匿名内部类.我还更新了一些逻辑来显示OnActivityResult()收到的URI:

namespace Scratch.fileUpload {    [Activity (Label = "Scratch.fileUpload", MainLauncher = true)]    public class Activity1 : Activity    {        private WebVIEw wv;        private IValueCallback mUploadMessage;        const int filechooserResultcode = 1;        protected overrIDe voID OnCreate (Bundle bundle)        {            base.OnCreate (bundle);            wv = new WebVIEw (this);            wv.SetWebVIEwClIEnt(new WebVIEwClIEnt());            wv.SetWebChromeClIEnt(new MyOpenfileWebChromeClIEnt(uploadMsg => {                        mUploadMessage = uploadMsg;                        var intent = new Intent (Intent.ActionGetContent);                        intent.Addcategory(Intent.categoryOpenable);                        intent.SetType("image/*");                        StartActivityForResult(Intent.CreateChooser(intent, "file Chooser"),                            filechooserResultcode);            }));            SetHTML(null);            SetContentVIEw(wv);        }        voID SetHTML(string filename)        {            string HTML = @"<HTML><body><h1>Hello, world!</h1><p>input Box:</p><input type=""file"" /><p>URI: " + filename + @"</body></HTML>";            wv.LoadData(HTML, "text/HTML", "utf-8");        }        protected overrIDe voID OnActivityResult (int requestCode, Result resultCode, Intent data)        {            base.OnActivityResult (requestCode, resultCode, data);            if (requestCode == filechooserResultcode) {                if (mUploadMessage == null)                    return;                var result = data == null || resultCode != Result.Ok                    ? null                    : data.Data;                SetHTML(result.ToString());                mUploadMessage.OnReceiveValue(result);                mUploadMessage = null;            }        }    }}

可悲的是,现在是时候采取纯粹的彻头彻尾的邪恶行为了. MyOpenfileWebChromeClIEnt的上述声明的问题在于它不起作用,原因与M0S’博客无法在匿名内部类声明中使用@OverrIDe相同:你构建应用程序的androID.jar不会声明openfileChooser()方法.

构建过程将生成Android Callable Wrappers,其中必须包含有效的Java代码.问题是生成的代码使用@OverrIDe来覆盖方法和接口方法,从而产生MyOpenfileWebChromeClIEnt的AndroID Callable Wrapper:

package scratch.fileupload;public class MyOpenfileWebChromeClIEntextends androID.webkit.WebChromeClIEnt{    static final String __md_methods;    static {        __md_methods =             "n_openfileChooser:(LandroID/webkit/ValueCallback;)V:GetopenfileChooserHandler\n" +            "";        mono.androID.Runtime.register ("Scratch.fileUpload.MyOpenfileWebChromeClIEnt, Scratch.fileUpload, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", MyOpenfileWebChromeClIEnt.class, __md_methods);    }    @OverrIDe    public voID openfileChooser (androID.webkit.ValueCallback p0)    {        n_openfileChooser (p0);    }    private native voID n_openfileChooser (androID.webkit.ValueCallback p0);    java.util.ArrayList refList;    public voID monodroIDAddReference (java.lang.Object obj)    {        if (refList == null)            refList = new java.util.ArrayList ();        refList.add (obj);    }    public voID monodroIDClearReferences ()    {        if (refList != null)            refList.clear ();    }}

显然,MyOpenfileWebChromeClIEnt.openfileChooser()上的@OverrIDe会产生编译错误,那么我们如何才能使这个工作呢?通过提供我们自己的@OverrIDe注释!

package scratch.fileupload;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.soURCE)public @interface OverrIDe {}

将上述内容放入名为OverrIDe.java的文件中,将其添加到项目中,并将其Build *** 作设置为AndroIDJavaSource.

生成的项目有效,因为我们在与MyOpenfileWebChromeClIEnt类型相同的包中提供自定义@OverrIDe注释. (这因此要求您知道生成的包名称是什么,并且为每个包提供单独的@OverrIDe注释.)同一包中的类型优先于导入的名称,甚至来自java的名称.lang,所以我们的自定义@OverrIDe注释不仅编译,它还被MyOpenfileWebChromeClIEnt androID可调用包装器使用,优先于java.lang.OverrIDe注释.

我确实说这是纯粹的不朽邪恶,不是吗?

总结

以上是内存溢出为你收集整理的c# – Mono for Android,WebView输入字段filechooser不起作用全部内容,希望文章能够帮你解决c# – Mono for Android,WebView输入字段filechooser不起作用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1117664.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存