Flutter Chime js sdk 使用
之前项目用过但是是针对 ios 和 android 的,现在需要针对 web 的,所以需要重新记录下。
问题
先搞清楚,硬件的权限和 web 的权限,因为用到摄像头和麦克风。
基本原理就是 web 上用到摄像头和麦克风,需要在启动 web 前先把平台的相关权限申请好。
webview_flutter 还是 inappwebview
开始用的 webview_flutter,但是发现权限问题,好一通网上查找都没解决,因为之前项目里 chime 本身原来接入的就是 inappwebview,所以索性切换到 inappwebview。
安卓配置
-
在
AndroidManifest.xml
中添加权限:<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <!-- <uses-permission android:name="android.permission.BLUETOOTH" />--> <!-- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />--> <application android:label="test_pdf_editor" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> <activity/> </application> </manifest>
-
app/build.gradle 中添加版本:
android { ... defaultConfig { ... minSdk = 28 // 最低版本 23 以上 } }
-
dart 中使用
/// 一次性请求摄像头 & 麦克风权限 static Future<void> _requestCameraAndMicrophonePermission() async { final statuses = await [ Permission.camera, Permission.microphone, ].request(); // 分别检查状态 final cameraStatus = statuses[Permission.camera]; final micStatus = statuses[Permission.microphone]; // 摄像头权限 if (cameraStatus != null && cameraStatus.isGranted) { debugPrint('Camera permission granted'); } else if (cameraStatus != null && cameraStatus.isPermanentlyDenied) { debugPrint('Camera permission permanently denied'); // 引导用户去系统设置开启权限 await openAppSettings(); } else { debugPrint('Camera permission denied'); } // 麦克风权限 if (micStatus != null && micStatus.isGranted) { debugPrint('Microphone permission granted'); } else if (micStatus != null && micStatus.isPermanentlyDenied) { debugPrint('Microphone permission permanently denied'); await openAppSettings(); } else { debugPrint('Microphone permission denied'); } }
-
在需要使用摄像头和麦克风的地方调用,最后这个初始化 webview 的代码比较重要,因为可能 voice input 有声音,但是 voice output 没有声音,所以需要设置
mediaPlaybackRequiresUserGesture
为false
,允许自动播放,也就是麦克风和 speaker,网页上显示 speaker 下拉框是 device selection unavailable 基本没有关系,做这个配置就可以了。await _requestCameraAndMicrophonePermission(); InAppWebView( // 初始 URL initialUrlRequest: URLRequest(url: WebUri(widget.url)), // 初始配置,比如是否允许 JS initialSettings: InAppWebViewSettings( javaScriptEnabled: true, mediaPlaybackRequiresUserGesture: false, // 自動再生を許可 useOnLoadResource: true, useShouldOverrideUrlLoading: true, allowsInlineMediaPlayback: true, mixedContentMode: MixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW, ),
windows webview 問題
先开始一直用的 webview_windows,但是发现权限问题,也就是点击打开 web 页面的时候,没有弹出权限弹窗,然后页面显示异常。然后切换到 desktop_webview_window 后,发现正常出现了弹窗。
アプリ和 windows 包区分的问题
结论
- Flutter 并不支持在 pubspec.yaml 内直接区分平台添加依赖,因此没法在 pubspec 中做“只在 Windows 下引入 desktop_webview_window”之类的写法。
- 通常我们会把所有可能用到的平台包都放进
dependencies
,然后在代码层面用条件导入或“分文件”去避免在非目标平台上实际导入并编译那些插件。 - 这在实际项目中是非常常见且推荐的做法,一般不会对不相关平台编译造成任何阻塞或报错,也不会有太大性能或打包体积的负面影响。
简单总结:
不需要也无法在 pubspec 中“区分”来引入,直接一起引入就好,关键是要用条件导入或分文件来控制代码层面对插件的引用,避免不兼容问题。