Xamarin WebView相机上传两张图片异常:仅第一张成功的原因与解决
Hey there! Let's figure out why only your first image upload works and the second one fails in your WebView-based camera upload setup. This is a super common issue with Android WebView file uploads, so let's break down the most likely causes and how to fix them.
Common Causes & Fixes
1. Missing Callback Reset After First Upload
The biggest culprit here is usually forgetting to reset the WebView's file upload callback after the first successful upload. Android WebView requires that once you've handled a file selection result, you clear the ValueCallback<Uri[]> reference—if you don't, subsequent file upload requests will be ignored because the WebView thinks the previous callback is still pending.
Fix:
After you pass the image Uri to the callback in your renderer, immediately set the callback to null. Here's how that might look in your MyCustomwebviewRenderer.cs:
// Inside your method that handles the Activity result public void OnActivityResult(int resultCode, Intent data) { if (_filePathCallback == null) return; Uri[] results = null; if (resultCode == Result.Ok && _activity.CameraImageUri != null) { results = new Uri[] { _activity.CameraImageUri }; } // Send results to WebView _filePathCallback.OnReceiveValue(results); // Critical: Reset callback to null for next upload _filePathCallback = null; }
2. Stale Callback Reference in WebChromeClient
If your WebChromeClient isn't updating the callback reference every time a new file upload is requested, the second upload will try to use the already-completed first callback.
Fix:
In your OnShowFileChooser override, always save the latest callback (overwriting any old one) before launching the camera:
public override bool OnShowFileChooser(Android.Webkit.WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // Save the new callback, replacing any existing one _renderer._filePathCallback = filePathCallback; // Launch your camera flow _renderer._activity.LaunchCameraForUpload(); return true; }
3. Activity Result Handling Issues
If your MainActivity isn't properly passing results back to the WebView renderer, or isn't generating a unique image Uri for each upload, the second image might be overwritten or never reach the WebView.
Fix:
- Generate a unique file name for each camera capture to avoid overwriting the first image:
public void LaunchCameraForUpload() { // Use a timestamp to ensure unique file names var fileName = $"upload_{DateTime.Now.Ticks}.jpg"; var storageDir = GetExternalFilesDir(Android.OS.Environment.DirectoryPictures); var imageFile = new File(storageDir, fileName); CameraImageUri = FileProvider.GetUriForFile(this, $"{PackageName}.fileprovider", imageFile); // Launch camera intent with proper permissions var takePictureIntent = new Intent(MediaStore.ActionImageCapture); takePictureIntent.PutExtra(MediaStore.ExtraOutput, CameraImageUri); takePictureIntent.AddFlags(ActivityFlags.GrantReadUriPermission); StartActivityForResult(takePictureIntent, 100); }
- Make sure your
MainActivitypasses the result directly to the renderer:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == 100) { _webViewRenderer?.OnActivityResult((int)resultCode, data); } }
4. Permission or Uri Permission Issues
Sometimes the second upload fails because you're not rechecking permissions, or the Uri from the first upload doesn't have the right permissions for the second request.
Fix:
- Ensure you request camera and storage permissions (for Android 13+, use
READ_MEDIA_IMAGESinstead ofWRITE_EXTERNAL_STORAGE) every time before launching the camera, or check if permissions are still granted. - When creating the camera intent, add the
GrantReadUriPermissionflag to ensure the camera app can write to the Uri, and the WebView can read it later.
Quick Checklist to Verify
- After each upload, the
ValueCallback<Uri[]>is set tonull -
OnShowFileChooseralways updates the callback reference with the latest request - Each camera capture uses a unique file Uri
- Permissions are valid and granted for each upload attempt
- Activity results are correctly passed from
MainActivityto the WebView renderer
If you're still hitting issues after trying these fixes, feel free to share more snippets of your MyCustomwebviewRenderer.cs and Mainactivity.cs—I can help dig deeper into specific code paths!
内容的提问来源于stack exchange,提问作者Ufuk Zimmerman




