Xamarin Forms中WebView文件选择器无法添加相机拍摄/选取的图片
解决Xamarin Forms WebView选择图片后无法加载的问题
核心问题分析
你的代码缺少以下关键环节,导致选中的图片无法传递给WebView:
- 未保存
filePathCallback引用,无法在图片选择完成后回调WebView - 未实现
OnActivityResult方法处理图片选择结果 - Android 7.0+版本未使用
FileProvider生成安全URI,可能引发权限问题 - 相机拍照后的图片URI未正确传递回WebView
修正后的完整代码实现
首先,在AndroidManifest.xml中配置FileProvider:
<application ...> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
在Resources/xml目录下创建file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> <cache-path name="my_cache" path="." /> </paths>
修改WebViewClient的代码:
private Android.Webkit.IValueCallback mFilePathCallback; private const int INPUT_FILE_REQUEST_CODE = 100; private string mCameraPhotoPath; private Context mContext; public override bool OnShowFileChooser(Android.Webkit.WebView webView, Android.Webkit.IValueCallback filePathCallback, FileChooserParams fileChooserParams) { // 保存回调引用 mFilePathCallback = filePathCallback; Intent takePictureIntent = new Intent(MediaStore.ActionImageCapture); if (takePictureIntent.ResolveActivity(mContext.PackageManager) != null) { Java.IO.File photoFile = null; try { photoFile = createImageFile(); if (photoFile != null) { mCameraPhotoPath = photoFile.AbsolutePath; // 使用FileProvider生成安全URI Uri photoUri = FileProvider.GetUriForFile(mContext, mContext.PackageName + ".fileprovider", photoFile); takePictureIntent.PutExtra(MediaStore.ExtraOutput, photoUri); takePictureIntent.AddFlags(ActivityFlags.GrantReadUriPermission); } else { takePictureIntent = null; } } catch (Exception e) { Console.WriteLine("拍照文件创建失败: " + e.Message); takePictureIntent = null; } } Intent contentSelectionIntent = new Intent(Intent.ActionGetContent); contentSelectionIntent.AddCategory(Intent.CategoryOpenable); contentSelectionIntent.SetType("image/*"); // 限制选择图片类型 Intent[] intentArray = takePictureIntent != null ? new[] { takePictureIntent } : new Intent[0]; Intent chooserIntent = new Intent(Intent.ActionChooser); chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent); chooserIntent.PutExtra(Intent.ExtraTitle, "选择图片"); chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray); ((Activity)mContext).StartActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE); return true; } // 处理图片选择结果 public override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) return; Uri[] results = null; // 处理相机拍照结果 if (resultCode == Result.Ok && !string.IsNullOrEmpty(mCameraPhotoPath)) { Java.IO.File file = new Java.IO.File(mCameraPhotoPath); Uri uri = FileProvider.GetUriForFile(mContext, mContext.PackageName + ".fileprovider", file); results = new[] { uri }; } // 处理文件选择器结果 else if (data != null && resultCode == Result.Ok) { string dataString = data.DataString; if (!string.IsNullOrEmpty(dataString)) { results = new[] { Uri.Parse(dataString) }; } } // 将结果回调给WebView mFilePathCallback.OnReceiveValue(results); mFilePathCallback = null; mCameraPhotoPath = null; } private Java.IO.File createImageFile() { string timeStamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); string imageFileName = "JPEG_" + timeStamp + "_"; Java.IO.File storageDir = mContext.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures); return Java.IO.File.CreateTempFile(imageFileName, ".jpg", storageDir); }
关键修正点说明
- 保存回调引用:将
filePathCallback存储为成员变量,确保在结果返回时能回调WebView - 实现OnActivityResult:统一处理相机拍照和文件选择的结果,生成合法URI传递给WebView
- FileProvider适配:解决Android 7.0+的文件权限限制,避免
FileUriExposedException - 权限授予:为相机Intent添加临时URI读取权限,确保拍照后能正常访问图片文件
内容的提问来源于stack exchange,提问作者I'm Coder
相关产品推荐
相关产品推荐

