前言
最近项目中加了一个H5的链接,里面有拍照、选照片和文件,以前用的原生的WebView,iOS功能还可以正常弹窗,安卓死活没反应,就换了一种方案,使用InAppWebView看看。
实现过程
新建了页面,创建InAppWebView,具体代码如下:
import 'dart:collection';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:magic/assets/styles/app_color.dart';
import '../../../common/utils/routers/fluro_navigator.dart';
import '../../../common/widgets/reza_app_bar.dart';
class WebViewInAppScreen extends StatefulWidget {
const WebViewInAppScreen({
Key key,
@required this.url,
this.title,
this.type,
this.onWebProgress,
this.onWebResourceError,
this.onLoadFinished,
this.onWebTitleLoaded,
this.onWebViewCreated,
}) : super(key: key);
final String url;
final String title;
final String type;
final Function(int progress) onWebProgress;
final Function(String errorMessage) onWebResourceError;
final Function(String url) onLoadFinished;
final Function(String webTitle) onWebTitleLoaded;
final Function(InAppWebViewController controller) onWebViewCreated;
@override
State<WebViewInAppScreen> createState() => _WebViewInAppScreenState();
}
class _WebViewInAppScreenState extends State<WebViewInAppScreen> {
// GlobalKey可以获取到对应的Widget的State对象
// 当我们页面内容很多时,而需要改变的内容只有很少的一部分且在树的底层的时候,我们如何去实现增量更新/通常情况下有两种方式,第一种是通过方法的回调,去实现数据更新,第二种是通过GlobalKey
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController webViewController;
InAppWebViewOptions viewOptions = InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: true,
// applicationNameForUserAgent: "dface-yjxdh-webview",
);
// webview配置
// InAppWebViewGroupOptions viewOptions = InAppWebViewGroupOptions(
// // 跨平台配置
// crossPlatform: InAppWebViewOptions (
// useShouldOverrideUrlLoading: true,
// mediaPlaybackRequiresUserGesture: true,
// ),
// // android平台配置
// android: AndroidInAppWebViewOptions(
// //支持HybridComposition
// useHybridComposition: true
// ),
// // ios 平台配置
// ios: IOSInAppWebViewOptions(
// allowsInlineMediaPlayback: true,
// )
// );
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
webViewController?.clearCache();
super.dispose();
}
// 设置页面标题
void setWebPageTitle(data) {
if (widget.onWebTitleLoaded != null) {
widget.onWebTitleLoaded(data);
}
}
// flutter调用H5方法
void callJSMethod() {
}
//返回
void back() async {
bool canGoBack = await webViewController.canGoBack();
if (canGoBack) {
webViewController.goBack();
} else {
NavigatorUtils.goBack(context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: Platform.isIOS ? false : true,
appBar: RezaAppBar(
centerTitle: widget.title,
isBack: true,
isClose: true,
onBack: () {
back();
},
),
body: Column(
children: <Widget>[
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: viewOptions,
),
onWebViewCreated: (controller) {
webViewController = controller;
if (widget.onWebViewCreated != null) {
widget.onWebViewCreated(controller);
}
},
onTitleChanged: (controller, title) {
if (widget.onWebTitleLoaded != null) {
widget.onWebTitleLoaded(title);
}
},
onLoadStart: (controller, url) {},
shouldOverrideUrlLoading: (controller, navigationAction) async {
// 允许路由替换
return NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) async {
// 加载完成
widget.onLoadFinished(url.toString());
},
onProgressChanged: (controller, progress) {
if (widget.onWebProgress != null) {
widget.onWebProgress(progress);
}
},
onLoadError: (controller, Uri url, int code, String message) {
if (widget.onWebResourceError != null) {
widget.onWebResourceError(message);
}
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
},
),
),
],
),
);
}
}
运行,页面倒是加载出来了,但是一点击拍照的按钮就直接崩溃了,如下:
报错信息下面一大堆日志,关键报错的原因:
Couldn't find meta-data for provider with authority com.foton.general.flutter_inappwebview.fileprovider
崩溃原因:
相机权限默认是禁止的。直接跳转到相册。
开启相机权限,闪退。
授权被拒绝后,无法再弹出授权
无法直接跳转到相机拍照
所以就百度一番,原来是没加这个:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.flutter_inappwebview.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
要在project->app->android->app->src->mian里的 AndroidManifest.xml 的 application 中添加上面的代码,添加以上代码后,在相机权限开启的情况下,能正常弹出选择弹框了。
结果运行直接报错,下面的错误:
image.png倒是说的听明白的,没加tools:replace="android:authorities",建议就加上了:
添加的完整的配置参数:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.flutter_inappwebview.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/jshare_file_provider_paths" />
</provider>
完整的配置。
然后运行就OK了,可以拍照,选文件相册了,记录一下踩坑历程。
image.png
网友评论