资料
官方文档
源码
pubspec.yaml
name: flutter_project
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
dio: ^4.0.4
cupertino_icons: ^1.0.2
flutter_downloader: ^1.5.2
path_provider: ^2.0.0-nullsafety
flutter_inappwebview: ^5.3.2
permission_handler: ^5.1.0+2
url_launcher: ^6.0.0-nullsafety.4
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
安卓下设置
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
<provider
android:name="com.pichillilorenzo.flutter_inappwebview.InAppWebViewFileProvider"
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>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
IOS
<key>NSMicrophoneUsageDescription</key>
<string>Flutter requires acess to microphone.</string>
<key>NSCameraUsageDescription</key>
<string>Flutter requires acess to camera.</string>
const.dart
class Const {
static const String Route = "/";
static const String InAppBrowser = "/InAppBrowser";
static const String ChromeSafariBrowser = "/ChromeSafariBrowser";
static const String HeadlessInAppWebView = "/HeadlessInAppWebView";
}
main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'chrome_safari_browser_example.sceen.dart';
import 'const.dart';
import 'headless_in_app_webview.screen.dart';
import 'in_app_broser_example.screen.dart';
import 'in_app_webview_example.screen.dart';
Future main() async {
// 初始化Messenger
WidgetsFlutterBinding.ensureInitialized();
//await Permission.camera.request();
//await Permission.microphone.request();
//await Permission.storage.request();
if (Platform.isAndroid) {
// Debuging WebViews
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
var swAvailable = await AndroidWebViewFeature.isFeatureSupported(
AndroidWebViewFeature.SERVICE_WORKER_BASIC_USAGE);
var swInterceptAvailable = await AndroidWebViewFeature.isFeatureSupported(
AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST);
if (swAvailable && swInterceptAvailable) {
AndroidServiceWorkerController serviceWorkerController =
AndroidServiceWorkerController.instance();
serviceWorkerController.serviceWorkerClient = AndroidServiceWorkerClient(
shouldInterceptRequest: (request) async {
print(request);
return null;
},
);
}
}
runApp(MyApp());
}
Drawer myDrawer({required BuildContext context}) {
return Drawer(
child: ListView(
children: [
DrawerHeader(
child: Text('flutter_inappbrowser example'),
decoration: BoxDecoration(color: Colors.blue),
),
ListTile(
title: Text('InAppBrowser'),
onTap: () {
Navigator.pushReplacementNamed(context, Const.InAppBrowser);
},
),
ListTile(
title: Text('ChromeSafariBrowser'),
onTap: () {
Navigator.pushReplacementNamed(context, Const.ChromeSafariBrowser);
},
),
ListTile(
title: Text('InAppWebView'),
onTap: () {
Navigator.pushReplacementNamed(context, Const.Route);
},
),
ListTile(
title: Text('HeadlessInAppWebView'),
onTap: () {
Navigator.pushReplacementNamed(context, Const.HeadlessInAppWebView);
},
),
],
),
);
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: Const.Route,
routes: {
Const.Route: (context) => InAppWebViewExampleScreen(),
Const.InAppBrowser: (context) => InAppBrowserExampleScreen(),
Const.ChromeSafariBrowser: (context) =>
ChromeSafariBrowserExampleScreen(),
Const.HeadlessInAppWebView: (context) =>
HeadlessInAppWebViewExampleScreen(),
},
);
}
}
in_app_webview_example.screen.dart
import 'dart:collection';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';
import 'main.dart';
class InAppWebViewExampleScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() => _InAppWebViewExampleScreenState();
}
class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true, // 是否需要跳转
mediaPlaybackRequiresUserGesture: false, // 设置为true,方式H5的音频自动播放
),
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: [
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/serch?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")),
//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 canLaunch(url)) {
await launch(url);
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: [
ElevatedButton(
onPressed: () {
webViewController?.goBack();
},
child: Icon(Icons.arrow_back),
),
ElevatedButton(
onPressed: () {
webViewController?.goForward();
},
child: Icon(Icons.arrow_forward),
),
ElevatedButton(
onPressed: () {
webViewController?.reload();
},
child: Icon(Icons.refresh),
),
],
),
],
),
),
);
}
}
in_app_broser_example.screen.dart
import 'dart:collection';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main.dart';
class MyInAppBrowser extends InAppBrowser {
MyInAppBrowser({
int? windowId,
UnmodifiableListView<UserScript>? initialUserScripts,
}) : super(windowId: windowId, initialUserScripts: initialUserScripts);
@override
void onBrowserCreated() {
super.onBrowserCreated();
print("Browser Created!");
}
@override
void onLoadStart(Uri? url) {
super.onLoadStart(url);
print("Started $url");
}
@override
void onLoadStop(Uri? url) {
super.onLoadStop(url);
pullToRefreshController?.endRefreshing();
print("Stopped $url");
}
@override
void onLoadError(Uri? url, int code, String message) {
super.onLoadError(url, code, message);
pullToRefreshController?.endRefreshing();
print("Can't load $url.. Error:$message");
}
@override
void onProgressChanged(int progress) {
super.onProgressChanged(progress);
if (progress == 100) {
pullToRefreshController?.endRefreshing();
}
print("Progress: $progress");
}
@override
void onExit() {
super.onExit();
print("Browser closed!");
}
@override
Future<NavigationActionPolicy?>? shouldOverrideUrlLoading(
NavigationAction navigationAction) {
print("Override ${navigationAction.request.url}");
return super.shouldOverrideUrlLoading(navigationAction);
}
@override
void onLoadResource(LoadedResource resource) {
super.onLoadResource(resource);
print("Started at: " +
resource.startTime.toString() +
"ms ----> duration: " +
resource.duration.toString() +
"ms " +
(resource.url ?? '').toString());
}
@override
void onConsoleMessage(ConsoleMessage consoleMessage) {
super.onConsoleMessage(consoleMessage);
print("""
console output:
message : ${consoleMessage.message}
messageLevel: ${consoleMessage.messageLevel.toValue()}
""");
}
}
class InAppBrowserExampleScreen extends StatefulWidget {
final MyInAppBrowser browser = new MyInAppBrowser();
@override
State<StatefulWidget> createState() => _InAppBrowserExampleScreenState();
}
class _InAppBrowserExampleScreenState extends State<InAppBrowserExampleScreen> {
late PullToRefreshController pullToRefreshController;
@override
void initState() {
super.initState();
pullToRefreshController = PullToRefreshController(
options: PullToRefreshOptions(
color: Colors.black,
),
onRefresh: () async {
if (Platform.isAndroid) {
widget.browser.webViewController.reload();
} else if (Platform.isIOS) {
widget.browser.webViewController.loadUrl(
urlRequest: URLRequest(
url: await widget.browser.webViewController.getUrl(),
),
);
}
},
);
widget.browser.pullToRefreshController = pullToRefreshController;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('InAppBrowser')),
drawer: myDrawer(context: context),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
await widget.browser.openUrlRequest(
urlRequest: URLRequest(url: Uri.parse("https://flutter.dev")),
options: InAppBrowserClassOptions(
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
),
),
),
);
},
child: Text("Open In-App Browser"),
),
Container(height: 40),
ElevatedButton(
onPressed: () async {
await InAppBrowser.openWithSystemBrowser(
url: Uri.parse("https://flutter.dev/"));
},
child: Text('Open System Broser'),
),
],
),
),
);
}
}
headless_in_app_webview.screen.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main.dart';
class HeadlessInAppWebViewExampleScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HeadlessInAppWebViewExampleScreenState();
}
}
class _HeadlessInAppWebViewExampleScreenState
extends State<HeadlessInAppWebViewExampleScreen> {
HeadlessInAppWebView? headlessWebView;
String url = "";
@override
void initState() {
super.initState();
headlessWebView = HeadlessInAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse("https://flutter.dev"),
),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(),
),
onWebViewCreated: (controller) {
print('HeadlessInAppWebView created!');
},
onConsoleMessage: (controller, consoleMessage) {
print('CONSOLE MESSAGE: ' + consoleMessage.message);
},
onLoadStart: (controller, url) async {
print("onLoadStart $url");
setState(() {
this.url = url.toString();
});
},
onLoadStop: (controller, url) async {
print("onLoadStop $url");
setState(() {
this.url = url.toString();
});
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {
print("onUpdateVisitedHistory $url");
setState(() {
this.url = url.toString();
});
}
);
}
@override
void dispose() {
super.dispose();
headlessWebView?.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: AppBar(title: Text("HeadlessInAppWebView"))),
drawer: myDrawer(context: context),
body: SafeArea(
child: Column(
children: [
Container(
padding: EdgeInsets.all(20.0),
child: Text(
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) +
"..." : url}"
),
),
Center(
child: ElevatedButton(
onPressed: () async {
await headlessWebView?.dispose();
await headlessWebView?.run();
},
child: Text("Run HeadlessInAppWebView"),
),
),
Center(
child: ElevatedButton(
onPressed: () async {
try {
await headlessWebView?.webViewController.evaluateJavascript(
source: """console.log('Here is the message!');""",
);
} on MissingPluginException {
print(
"HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!");
}
},
child: Text("Send console.log message"),
),
),
Center(
child: ElevatedButton(
onPressed: (){
headlessWebView?.dispose();
},
child: Text("Dispose HeadlessInAppWebView"),
),
),
],
),
),
);
}
}
chrome_safari_browser_example.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'main.dart';
class MyChromeSafariBrowser extends ChromeSafariBrowser {
@override
void onOpened() {
super.onOpened();
print("ChromeSafari browser opened");
}
@override
void onCompletedInitialLoad() {
super.onCompletedInitialLoad();
print("ChromeSafari browser initial load completed");
}
@override
void onClosed() {
super.onClosed();
print("ChromeSafari browser closed");
}
}
class ChromeSafariBrowserExampleScreen extends StatefulWidget {
final ChromeSafariBrowser browser = MyChromeSafariBrowser();
@override
State<StatefulWidget> createState() =>
_ChromeSafariBrowserExampleScreenState();
}
class _ChromeSafariBrowserExampleScreenState
extends State<ChromeSafariBrowserExampleScreen> {
@override
void initState() {
widget.browser.addMenuItem(
ChromeSafariBrowserMenuItem(
id: 1,
label: 'Custom item menu 1 clicked!',
action: (url, title) {
print('Custom item menu 1 clicked!');
print(url);
print(title);
},
),
);
widget.browser.addMenuItem(ChromeSafariBrowserMenuItem(
id: 2,
label: 'Cusstom item menu 2 clicked!',
action: (url, title) {
print('Custom item menu 2');
print(url);
print(title);
},
));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ChromeSafariBrowser')),
drawer: myDrawer(context: context),
body: Center(
child: ElevatedButton(
onPressed: () async {
await widget.browser.open(
url: Uri.parse("https://flutter.dev/"),
options: ChromeSafariBrowserClassOptions(
android: AndroidChromeCustomTabsOptions(
addDefaultShareMenuItem: false,
keepAliveEnabled: true,
),
ios: IOSSafariOptions(
dismissButtonStyle: IOSSafariDismissButtonStyle.CLOSE,
presentationStyle:
IOSUIModalPresentationStyle.OVER_FULL_SCREEN),
),
);
},
child: Text("Open Chrome Safari Browser"),
),
),
);
}
}