记录踩坑
- Flutter 3.3.0
- webview_flutter ^4.4.1
- android 13 \ android 11
踩坑过程
- 如题,公司APP项目绝大部分都是采用 web + flutter 的混合开发模式。
- 开发流程都是先完成web端开发,再去套入 Flutter APP webview 内,再去实现两端的交互。
- input 元素 type 为 "file"时,在 android 手机端无论是内置浏览器还是微信直接打开网页,都可以通过这个调用手机摄像头拍照或者文件选择相册。
ini
复制代码
<input type="file" >
- 原本以为拍照上传图片功能不出意外,一切顺利。可当套入flutter 中的 webview 时,点击 input 却没用了,完全没反应。
- 分析问题出现原因
- 权限问题:一开始以为是 APP 权限问题,在 AndroidManifest.xml 把 android 摄像头、文件读取权限全加上,发现也不行。
- 安全限制:因为还在开发阶段,所以 webview url 地址用的是本机ip,所以猜想可能是没用 https 的原因。
- 这些问题一一排查完,都不是没反应的原因。
解决问题
- 利用 webview_flutter 的 setOnShowFileSelector API
- 需要安装 webview_flutter_android、image_picker
ini
复制代码
// 初始化时设置到 webview 的 controller
void setupInputFile() async {
if (Platform.isAndroid) {
final controller = (_controller.platform as webview_flutter_android.AndroidWebViewController);
await controller.setOnShowFileSelector(_androidFilePicker);
}
}
// 设置文件选择方法
Future<List<String>> _androidFilePicker(webview_flutter_android.FileSelectorParams params) async {
final picker = image_picker.ImagePicker();
final source = await showImageDialog();
if (source == null) {
return [];
}
final photo = await picker.pickImage(source: source!);
if (photo == null) {
return [];
}
return [File(photo.path).uri.toString()];
// 压缩图片功能
// final imageData = await photo.readAsBytes();
// final decodedImage = image.decodeImage(imageData)!;
//
// final jpg = image.encodeJpg(decodedImage, quality: 50);
//
// final filePath = (await getTemporaryDirectory()).uri.resolve(
// './image_${DateTime.now().microsecondsSinceEpoch}.jpg',
// );
// final file = await File.fromUri(filePath).create(recursive: true);
// await file.writeAsBytes(jpg, flush: true);
//
// return [file.uri.toString()];
}
- 添加如上方法,webview 在安卓端也能成功调用摄像头和系统文件管理
- 最终效果如下图
参考文章