模拟器启动拍照页面触发System.NotImplementedException错误求助
嘿,这个问题我太熟了!你碰到的System.NotImplementedException本质上是Xamarin的「便携类库(PCL)/共享项目只做抽象,不做实现」特性导致的——你在共享代码里调用了相机功能,但便携版本的程序集根本没有写具体的平台拍照逻辑,所有实际操作都得靠各个平台项目(Android、iOS这些)来提供。
下面给你一步步解决的方案:
1. 确保所有平台项目都引用了正确的NuGet包
不管你用的是Xamarin.Essentials(现在的主流选择)还是Xamarin.Plugins.Media这类第三方插件,一定要在每个平台的主项目里安装对应的NuGet包,而不只是在PCL/共享项目里装。
比如用Xamarin.Essentials的话,打开你的Android、iOS、UWP项目,分别右键选择「管理NuGet程序包」,搜索安装Xamarin.Essentials。
2. 配置平台权限(关键!)
模拟器和真机一样,需要权限才能访问相机,没配置的话不仅会报错,还可能直接闪退:
- Android:打开
AndroidManifest.xml,添加以下权限:<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> - iOS:打开
Info.plist,添加NSCameraUsageDescription键,值填你需要相机的原因(比如「需要拍摄照片上传」),iOS10+必须要这个描述。
3. 正确调用相机功能(避免直接实例化平台类)
如果你是自己写的相机接口,一定要用Xamarin的DependencyService来获取平台实现:
- 先在PCL里定义接口:
public interface ICameraService { Task<byte[]> TakePhotoAsync(); } - 然后在Android项目里写实现类:
[assembly: Dependency(typeof(CameraServiceAndroid))] namespace YourApp.Droid { public class CameraServiceAndroid : ICameraService { public async Task<byte[]> TakePhotoAsync() { // 这里写Android平台的拍照逻辑,比如用Xamarin.Essentials var photo = await MediaPicker.CapturePhotoAsync(); using var stream = await photo.OpenReadAsync(); var bytes = new byte[stream.Length]; await stream.ReadAsync(bytes, 0, (int)stream.Length); return bytes; } } } - iOS项目同理写
CameraServiceiOS,然后在PCL里这样调用:var cameraService = DependencyService.Get<ICameraService>(); var photoBytes = await cameraService.TakePhotoAsync();
如果用Xamarin.Essentials的话更简单,直接在共享代码里调用MediaPicker.CapturePhotoAsync()就行,只要平台项目装了包、配了权限,底层会自动处理平台实现。
4. 模拟器的额外设置
有些模拟器默认没开启相机模拟:
- Android模拟器:打开AVD管理器,编辑你的模拟器,在「Show Advanced Settings」里找到「Camera」选项,把前后摄像头设置为「Webcam0」或者其他可用的摄像头。
- iOS模拟器:默认会模拟相机,但如果还是不行,可以重启模拟器或者检查系统权限设置。
最后再提醒一句:绝对不要在PCL/共享项目里直接引用平台专属的命名空间(比如Android的Android.Hardware.Camera),所有跨平台的功能都要通过抽象层或者官方的跨平台库来实现。
内容的提问来源于stack exchange,提问作者Stephane

