You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Xamarin Forms WebView在ASP.NET网站中调用原生相机并加载照片

我来帮你搞定这个需求!要在Xamarin WebView里让ASP.NET网站直接唤起原生相机,拍完还能把照片无缝传回网页显示,核心是WebView和原生代码的双向交互。下面分平台给你一步步实现:

整体核心逻辑

网页端通过JS调用原生端的相机启动方法 → 原生端唤起系统相机并处理拍照结果 → 把照片转成Base64格式(方便直接传给网页)→ 原生端调用网页的JS回调方法,把Base64数据传回去 → ASP.NET网页加载并显示照片

Android 端实现

1. 配置权限

首先在AndroidManifest.xml里添加相机权限,Android 6.0以上还要动态申请权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />

2. 实现JS与原生的交互类

写一个辅助类,把相机操作暴露给JS:

public class CameraJsInterface : Java.Lang.Object
{
    private readonly Activity _activity;
    private readonly WebView _webView;
    public static readonly int CameraRequestCode = 1001;

    public CameraJsInterface(Activity activity, WebView webView)
    {
        _activity = activity;
        _webView = webView;
    }

    [JavascriptInterface] // 必须加这个注解,JS才能调用
    public void OpenCamera()
    {
        // 先检查动态权限
        if (ContextCompat.CheckSelfPermission(_activity, Manifest.Permission.Camera) != Permission.Granted)
        {
            ActivityCompat.RequestPermissions(_activity, new[] { Manifest.Permission.Camera }, CameraRequestCode);
            return;
        }

        // 启动系统相机
        var takePictureIntent = new Intent(MediaStore.ActionImageCapture);
        if (takePictureIntent.ResolveActivity(_activity.PackageManager) != null)
        {
            _activity.StartActivityForResult(takePictureIntent, CameraRequestCode);
        }
    }

    // 处理拍照结果,这个方法要在Activity里调用
    public void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        if (requestCode == CameraRequestCode && resultCode == Result.Ok && data != null)
        {
            // 获取拍照的Bitmap
            var imageBitmap = (Bitmap)data.Extras.Get("data");
            // 转成Base64
            using (var stream = new MemoryStream())
            {
                imageBitmap.Compress(Bitmap.CompressFormat.Jpeg, 80, stream);
                byte[] byteArray = stream.ToArray();
                string base64String = Convert.ToBase64String(byteArray);

                // 调用网页的JS回调,把Base64传回去
                _webView.Post(() =>
                {
                    _webView.EvaluateJavascript($"window.onCameraPhotoTaken('{base64String}')", null);
                });
            }
            // 回收Bitmap避免内存泄漏
            imageBitmap.Recycle();
        }
        else
        {
            // 拍照取消,通知网页
            _webView.Post(() =>
            {
                _webView.EvaluateJavascript("window.onCameraPhotoTaken(null)", null);
            });
        }
    }
}

3. 配置WebView并绑定交互类

在你的WebView所在的Activity里初始化WebView:

private WebView _webView;
private CameraJsInterface _cameraJsInterface;

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.Main);

    _webView = FindViewById<WebView>(Resource.Id.webView);
    _webView.Settings.JavaScriptEnabled = true; // 必须开启JS

    _cameraJsInterface = new CameraJsInterface(this, _webView);
    _webView.AddJavascriptInterface(_cameraJsInterface, "NativeCamera"); // 给JS暴露的对象名

    // 加载你的ASP.NET网站
    _webView.LoadUrl("https://your-aspnet-site.com");
}

// 重写OnActivityResult,把结果传给相机辅助类
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    _cameraJsInterface.OnActivityResult(requestCode, resultCode, data);
}

// 处理权限申请结果
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    if (requestCode == CameraJsInterface.CameraRequestCode)
    {
        if (grantResults.Length > 0 && grantResults[0] == Permission.Granted)
        {
            _cameraJsInterface.OpenCamera();
        }
        else
        {
            // 用户拒绝权限,通知网页
            _webView.EvaluateJavascript("window.onCameraPermissionDenied()", null);
        }
    }
}
iOS 端实现

1. 配置相机权限

在Info.plist里添加相机权限说明(iOS必须要):

<key>NSCameraUsageDescription</key>
<string>需要使用相机拍摄照片</string>

2. 实现WKWebView的消息处理

iOS推荐用WKWebView,需要实现WKScriptMessageHandler来接收JS的消息:

public class ViewController : UIViewController, IWKScriptMessageHandler
{
    private WKWebView _webView;
    private UIImagePickerController _imagePicker;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        // 配置WKWebView
        var config = new WKWebViewConfiguration();
        config.UserContentController.AddScriptMessageHandler(this, "openCamera"); // 注册JS消息名

        _webView = new WKWebView(View.Bounds, config);
        View.AddSubview(_webView);

        // 加载ASP.NET网站
        _webView.LoadRequest(new NSUrlRequest(new NSUrl("https://your-aspnet-site.com")));
    }

    // 接收JS发来的openCamera消息
    public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
    {
        if (message.Name == "openCamera")
        {
            // 检查相机权限
            AVAuthorizationStatus status = AVCaptureDevice.GetAuthorizationStatus(AVMediaType.Video);
            if (status == AVAuthorizationStatus.Authorized)
            {
                OpenCamera();
            }
            else if (status == AVAuthorizationStatus.NotDetermined)
            {
                AVCaptureDevice.RequestAccessForMediaTypeAsync(AVMediaType.Video).ContinueWith(t =>
                {
                    if (t.Result)
                    {
                        InvokeOnMainThread(OpenCamera);
                    }
                    else
                    {
                        // 权限被拒,通知网页
                        _webView.EvaluateJavaScript("window.onCameraPermissionDenied()", null);
                    }
                });
            }
            else
            {
                _webView.EvaluateJavaScript("window.onCameraPermissionDenied()", null);
            }
        }
    }

    private void OpenCamera()
    {
        _imagePicker = new UIImagePickerController();
        _imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
        _imagePicker.MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.Camera);
        _imagePicker.FinishedPickingMedia += OnImagePickerFinished;
        _imagePicker.Canceled += OnImagePickerCanceled;
        PresentViewController(_imagePicker, true, null);
    }

    // 处理拍照完成
    private void OnImagePickerFinished(object sender, UIImagePickerMediaPickedEventArgs e)
    {
        var image = e.OriginalImage;
        // 转成Base64
        var imageData = image.AsJPEG(0.8f);
        string base64String = imageData.GetBase64EncodedString(NSDataBase64EncodingOptions.EndLineWithLineFeed);

        // 调用网页JS回调
        _webView.EvaluateJavaScript($"window.onCameraPhotoTaken('{base64String}')", null);

        _imagePicker.DismissViewController(true, null);
        _imagePicker.Dispose();
    }

    // 处理拍照取消
    private void OnImagePickerCanceled(object sender, EventArgs e)
    {
        _webView.EvaluateJavaScript("window.onCameraPhotoTaken(null)", null);
        _imagePicker.DismissViewController(true, null);
        _imagePicker.Dispose();
    }

    // 页面销毁时移除消息处理,避免内存泄漏
    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        _webView.Configuration.UserContentController.RemoveScriptMessageHandler("openCamera");
    }
}
ASP.NET 网页端配合

在你的ASP.NET页面里添加按钮和图片容器,写JS代码来调用原生相机并处理返回的照片:

<button id="takePhotoBtn">拍摄照片</button>
<img id="photoPreview" src="" alt="拍摄的照片" style="max-width: 100%; margin-top: 20px;" />

<script>
// 兼容Android和iOS的相机调用函数
function openNativeCamera() {
    if (typeof NativeCamera !== 'undefined') {
        // Android端
        NativeCamera.OpenCamera();
    } else if (typeof webkit !== 'undefined' && webkit.messageHandlers && webkit.messageHandlers.openCamera) {
        // iOS端
        webkit.messageHandlers.openCamera.postMessage(null);
    } else {
        alert("当前环境不支持原生相机调用");
    }
}

// 原生端回调的拍照结果处理函数
window.onCameraPhotoTaken = function(base64Data) {
    const imgElement = document.getElementById('photoPreview');
    if (base64Data) {
        imgElement.src = 'data:image/jpeg;base64,' + base64Data;
    } else {
        alert("拍照已取消");
    }
}

// 权限被拒的处理函数
window.onCameraPermissionDenied = function() {
    alert("请允许相机权限才能拍摄照片");
}

// 绑定按钮点击事件
document.getElementById('takePhotoBtn').addEventListener('click', openNativeCamera);
</script>
注意事项
  • 照片压缩:上面的代码里都设置了压缩质量(Android是80,iOS是0.8),避免Base64字符串过大导致传输卡顿。
  • 权限处理:一定要处理用户拒绝权限的情况,给用户友好提示。
  • 内存管理:iOS端记得在页面销毁时移除ScriptMessageHandler,防止内存泄漏;Android端的Bitmap要及时回收。

内容的提问来源于stack exchange,提问作者G. Nah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:59:26