Xamarin.Forms 如何正确调用 Android 与 iOS 原生SDK相机功能
跨平台调用Xamarin原生平台SDK的落地步骤
你之前尝试的接口+依赖注册的思路是完全正确的,找不到平台实现、拿不到原生能力的问题,基本都是注册环节漏写、平台层的原生API调用路径不对导致的,按以下流程调整即可:
1. 补全跨层接口的注册逻辑,解决平台实现找不到的问题
你在共享层定义的ICameraAccess接口只定义了方法签名,要让跨层解析能找到对应的平台实现,必须把两个平台项目的注册逻辑做扎实:
- 共享层的接口要完全基于通用类型定义方法,不能引入平台专属的类型引用,比如文档扫描场景的接口可以这么写:
public interface ICameraAccess { /// <summary>判断当前设备是否有可用相机,且已获得权限</summary> bool IsCameraAvailable { get; } /// <summary>调起原生文档扫描流程,返回扫描后的文件路径</summary> Task<string> StartDocumentScanAsync(CancellationToken cancelToken); } - 平台项目下的实现类,必须配置正确的依赖注册特性,这一步是最容易踩坑的:
- Android项目中,实现类要写在Droid项目的命名空间下,类是公共无参构造的,在类文件的最顶部、命名空间外面加上依赖注册标记:
// 必须写在文件顶层、类的外面,不然编译时扫描不到注册 [assembly: Dependency(typeof(AndroidCameraImpl))] namespace YourApp.Droid { // 实现类必须显式继承共享层的ICameraAccess接口 public class AndroidCameraImpl : ICameraAccess { // 这里直接写调用Android原生SDK的逻辑,没有任何跨层限制 public bool IsCameraAvailable { get { // 直接调用Android原生的权限检查API var context = Android.App.Application.Context; return context.PackageManager.CheckPermission( Android.Manifest.Permission.Camera, context.PackageName ) == Android.Content.PM.Permission.Granted; } } public async Task<string> StartDocumentScanAsync(CancellationToken cancelToken) { // 这里直接调Android的原生SDK:比如CameraX相机能力、ML Kit文档扫描模块,不需要经过任何跨层包装 // 拿到扫描结果后,转成通用的文件路径字符串返回给共享层即可 return await Task.FromResult("/sdcard/scan/result.pdf"); } } } - iOS项目的实现类逻辑完全一致,同样要在文件顶层加
[assembly: Dependency(typeof(IOSCameraImpl))]标记,实现类继承ICameraAccess接口
- Android项目中,实现类要写在Droid项目的命名空间下,类是公共无参构造的,在类文件的最顶部、命名空间外面加上依赖注册标记:
- 共享层调用时,直接通过
DependencyService.Resolve<ICameraAccess>()取实例即可,不能自己手动new平台实现类(共享层根本无法引用平台项目的类型)
2. 各平台可直接调用的原生相机/文档扫描能力
之前觉得找不到可用的平台专属功能,本质是没找对原生API的入口,两个平台的可用能力可以直接在实现类里调用:
- Android平台可用能力
- 基础相机:直接对接
Android.Hardware.Camera2、Xamarin绑定的CameraX组件,完全和原生Android开发的API调用逻辑一致 - 文档扫描:可以直接调用Google服务集成的ML Kit文档扫描模块,不需要自己写边缘检测、透视变换的算法
- 基础相机:直接对接
- iOS平台可用能力
- 基础相机:直接用
AVFoundation框架的采集能力、或者UIImagePickerController的系统相机界面 - 文档扫描:iOS13以上系统自带的
VNDocumentCameraViewController是系统级的文档扫描控制器,直接在实现类里present这个控制器,就能拿到带透视矫正、边缘检测的扫描结果,完全不需要第三方SDK
- 基础相机:直接用
3. 常见排查点(针对当前找不到实现的问题)
- 检查平台实现类的依赖注册特性是不是写在了类的内部,写在类里面的注册标记是不会被编译系统识别的
- 检查平台实现类是不是有公共无参构造,带参数的构造会导致依赖解析时无法实例化,直接抛找不到实现的异常
- 检查平台项目的目标版本是不是匹配要调用的原生API要求,比如要用iOS的原生文档扫描能力,平台项目的部署目标要设到13.0以上,不然编译时根本找不到对应的API入口
- 不要把平台专属的类型(比如Android的
Bitmap、iOS的UIImage)作为接口的返回值,这类类型在共享层无法直接解析,平台层拿到原生结果后,要转成通用的文件路径、字节数组这类跨层通用的类型再返回
内容的提问来源于stack exchange,提问作者Rajzer
相关产品推荐
相关产品推荐

