如何为Xamarin应用中的WebView授予文件浏览权限?
Xamarin WebView 文件选择失效解决方案
这个问题是因为Xamarin的WebView默认没有对接原生平台的文件选择逻辑,需要针对Android和iOS分别做自定义处理:
Android 平台处理
- 自定义
WebChromeClient,重写OnShowFileChooser方法拦截文件选择请求:
public class CustomWebChromeClient : WebChromeClient { private readonly Activity _activity; public static IValueCallback FileCallback; public CustomWebChromeClient(Activity activity) { _activity = activity; } public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams) { FileCallback = filePathCallback; var intent = fileChooserParams.CreateIntent(); try { _activity.StartActivityForResult(intent, 100); } catch (ActivityNotFoundException e) { FileCallback = null; return false; } return true; } }
- 在Activity的
OnActivityResult中处理选择结果:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == 100) { if (CustomWebChromeClient.FileCallback == null) return; var result = resultCode == Result.Ok ? WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data) : null; CustomWebChromeClient.FileCallback.OnReceiveValue(result); CustomWebChromeClient.FileCallback = null; } }
- 给WebView设置自定义的WebChromeClient:
webView.SetWebChromeClient(new CustomWebChromeClient(this));
- 确保在
AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
(Android 6.0+还需动态申请权限)
iOS 平台处理
- 创建自定义的
WKWebViewRenderer,实现IWKUIDelegate接口:
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))] namespace YourNamespace.iOS.Renderers { public class CustomWebViewRenderer : WkWebViewRenderer, IWKUIDelegate { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); if (NativeView != null) { ((WKWebView)NativeView).UIDelegate = this; } } [Export("webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:")] public void RunOpenPanel(WKWebView webView, WKOpenPanelParameters parameters, WKFrameInfo frame, Action<NSUrl[]> completionHandler) { var picker = new UIImagePickerController(); picker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary; picker.Delegate = new ImagePickerDelegate(completionHandler); UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(picker, true, null); } } public class ImagePickerDelegate : UIImagePickerControllerDelegate { private readonly Action<NSUrl[]> _completionHandler; public ImagePickerDelegate(Action<NSUrl[]> completionHandler) { _completionHandler = completionHandler; } public override void FinishedPickingMedia(UIImagePickerController picker, NSDictionary info) { var url = info.ValueForKey(UIImagePickerController.ImageUrl) as NSUrl; _completionHandler(new[] { url }); picker.DismissViewController(true, null); } public override void Canceled(UIImagePickerController picker) { _completionHandler(null); picker.DismissViewController(true, null); } } }
- 若需支持多种文件类型(不止图片),可替换
UIImagePickerController为UIDocumentPickerViewController实现更全面的文件选择。
内容的提问来源于stack exchange,提问作者KuroCoder
相关产品推荐
相关产品推荐

