[Bug]: Android FlutterBoostFragment无法触发onActivityForResult
请描述遇到的问题,以及您所期望的正确的结果
Android端 FlutterBoostFragment 内使用flutter_inappwebview 加载h5页面 input标签 选择相册后无法回调
请说明如何操作会遇到上述问题
项目工程:Flutter boost下面的example工程 新增 flutter_inappwebview: 5.8.0 open flutter fragment page 新增一个FlutterBoostFragment 新增一个InAppWebViewExampleScreen 加载https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_file 弹出图片选择后选择图片后展示 使用FlutterBoostActivity 作为容器新增InAppWebViewExampleScreen 加载该h5页面可以。
请问是什么原因
在下面填入关键复现代码
import 'dart:collection';
// import 'dart:convert';
import 'dart:io';
// import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
// import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
class InAppWebViewExampleScreen extends StatefulWidget {
@override
_InAppWebViewExampleScreenState createState() =>
new _InAppWebViewExampleScreenState();
}
class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
// useShouldOverrideUrlLoading: true,
// mediaPlaybackRequiresUserGesture: false
javaScriptEnabled: true,
disableHorizontalScroll: true,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
));
late PullToRefreshController pullToRefreshController;
late ContextMenu contextMenu;
String url = "";
double progress = 0;
final urlController = TextEditingController();
@override
void initState() {
super.initState();
contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(
androidId: 1,
iosId: "1",
title: "Special",
action: () async {
print("Menu item Special clicked!");
print(await webViewController?.getSelectedText());
await webViewController?.clearFocus();
})
],
options: ContextMenuOptions(hideDefaultSystemContextMenuItems: false),
onCreateContextMenu: (hitTestResult) async {
print("onCreateContextMenu");
print(hitTestResult.extra);
print(await webViewController?.getSelectedText());
},
onHideContextMenu: () {
print("onHideContextMenu");
},
onContextMenuActionItemClicked: (contextMenuItemClicked) async {
var id = (Platform.isAndroid)
? contextMenuItemClicked.androidId
: contextMenuItemClicked.iosId;
print("onContextMenuActionItemClicked: " +
id.toString() +
" " +
contextMenuItemClicked.title);
});
pullToRefreshController = PullToRefreshController(
options: PullToRefreshOptions(
color: Colors.blue,
),
onRefresh: () async {
if (Platform.isAndroid) {
webViewController?.reload();
} else if (Platform.isIOS) {
webViewController?.loadUrl(
urlRequest: URLRequest(url: await webViewController?.getUrl()));
}
},
);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("InAppWebView")),
// drawer: myDrawer(context: context),
body: SafeArea(
child: Column(children: <Widget>[
TextField(
decoration: InputDecoration(prefixIcon: Icon(Icons.search)),
controller: urlController,
keyboardType: TextInputType.url,
onSubmitted: (value) {
var url = Uri.parse(value);
if (url.scheme.isEmpty) {
url = Uri.parse("https://www.google.com/search?q=" + value);
}
webViewController?.loadUrl(urlRequest: URLRequest(url: url));
},
),
Expanded(
child: Stack(
children: [
InAppWebView(
key: webViewKey,
// contextMenu: contextMenu,
initialUrlRequest:
// URLRequest(url: Uri.parse("https://github.com/flutter")),
URLRequest(url: Uri.parse("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_file")),
// initialFile: "assets/index.html",
initialUserScripts: UnmodifiableListView<UserScript>([]),
initialOptions: options,
pullToRefreshController: pullToRefreshController,
onWebViewCreated: (controller) {
webViewController = controller;
},
onLoadStart: (controller, url) {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
androidOnPermissionRequest:
(controller, origin, resources) async {
return PermissionRequestResponse(
resources: resources,
action: PermissionRequestResponseAction.GRANT);
},
shouldOverrideUrlLoading:
(controller, navigationAction) async {
var uri = navigationAction.request.url!;
if (![
"http",
"https",
"file",
"chrome",
"data",
"javascript",
"about"
].contains(uri.scheme)) {
if (await canLaunchUrl(uri)) {
// Launch the App
await launchUrl(
uri,
);
// and cancel the request
return NavigationActionPolicy.CANCEL;
}
}
return NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) async {
pullToRefreshController.endRefreshing();
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
onLoadError: (controller, url, code, message) {
pullToRefreshController.endRefreshing();
},
onProgressChanged: (controller, progress) {
if (progress == 100) {
pullToRefreshController.endRefreshing();
}
setState(() {
this.progress = progress / 100;
urlController.text = this.url;
});
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {
setState(() {
this.url = url.toString();
urlController.text = this.url;
});
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
},
),
progress < 1.0
? LinearProgressIndicator(value: progress)
: Container(),
],
),
),
ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: Icon(Icons.arrow_back),
onPressed: () {
webViewController?.goBack();
},
),
ElevatedButton(
child: Icon(Icons.arrow_forward),
onPressed: () {
webViewController?.goForward();
},
),
ElevatedButton(
child: Icon(Icons.refresh),
onPressed: () {
webViewController?.reload();
},
),
],
),
])));
}
}
复现的平台
Both
Flutter SDK版本
3.7.9
FlutterBoost版本
main主分支
是否延迟初始化FlutterBoost
No
解决方案
根据flutter_inappwebview源码中的InAppWebViewChromeClient类,可以看到打开图片选择时所用的activity,是TabMainActivity,也就是FlutterBoostFragment所在的容器Activity并不是FlutterActivity,所以无法触发inAppWebview中依赖FlutterEngineConnectionRegistry的onActivityResult或FlutterEngineActivityPluginBinding的onActivityResult,也就无法把结果传回到Flutter。
这个只能说是flutter_inappwebview并不适配FlutterBoost。如果要得到正确的结果,可以尝试的一种方案是在FlutterBoostFragment的容器Activity中自行把Activity收到的onActivityResult的结果转发给Registry或PluginBinding的onActivityResult。另一种方案修改InAppWebViewChromeClient中的跳转方式,使用FlutterBoostFragment的startActivityForResult进行跳转,或者使用Activity Result API做类似处理。
根据
flutter_inappwebview源码中的InAppWebViewChromeClient类,可以看到打开图片选择时所用的activity,是TabMainActivity,也就是FlutterBoostFragment所在的容器Activity并不是FlutterActivity,所以无法触发inAppWebview中依赖FlutterEngineConnectionRegistry的onActivityResult或FlutterEngineActivityPluginBinding的onActivityResult,也就无法把结果传回到Flutter。这个只能说是
flutter_inappwebview并不适配FlutterBoost。如果要得到正确的结果,可以尝试的一种方案是在FlutterBoostFragment的容器Activity中自行把Activity收到的onActivityResult的结果转发给Registry或PluginBinding的onActivityResult。另一种方案修改InAppWebViewChromeClient中的跳转方式,使用FlutterBoostFragment的startActivityForResult进行跳转,或者使用Activity Result API做类似处理。
感谢解答