### Configure Web Platform for InAppWebView
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/intro
To ensure proper functionality of the Flutter InAppWebView plugin on the Web platform, you need to include the `web_support.js` file within the `
` section of your `web/index.html` file. This setup is crucial for web-specific features, though it's important to note that Flutter widgets overlaying iframes may not respond to mouse gestures, a known Flutter limitation that can be mitigated using the `pointer_interceptor` plugin.
```HTML
```
--------------------------------
### Handling Custom Scheme Resources with onLoadResourceWithCustomScheme in Dart
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/in-app-webview
This comprehensive Dart example demonstrates how to use `onLoadResourceWithCustomScheme` to serve custom resources for specific schemes. It includes platform-specific setup for `WebViewEnvironment` on Windows and `InAppWebViewSettings.resourceCustomSchemes` for other platforms, showing how to load a resource from assets and return it as a `CustomSchemeResponse`.
```Dart
import 'package:flutter/services.dart';
WebViewEnvironment? webViewEnvironment;
Future main() async {
//...
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) {
final availableVersion = await WebViewEnvironment.getAvailableVersion();
assert(availableVersion != null,
'Failed to find an installed WebView2 Runtime or non-stable Microsoft Edge installation.');
webViewEnvironment = await WebViewEnvironment.create(
settings: WebViewEnvironmentSettings(
userDataFolder: 'YOUR_CUSTOM_PATH',
customSchemeRegistrations: [
CustomSchemeRegistration(
scheme: "my-special-custom-scheme",
allowedOrigins: ['*'],
treatAsSecure: true,
hasAuthorityComponent: true)
]));
}
//...
}
//...
InAppWebView(
webViewEnvironment: webViewEnvironment,
initialUrlRequest: URLRequest(url: WebUri('https://example.com')),
initialSettings: InAppWebViewSettings(resourceCustomSchemes: ["my-special-custom-scheme"]),
onLoadResourceWithCustomScheme: (controller, request) async {
if (request.url.scheme == "my-special-custom-scheme") {
final bytes = await rootBundle.load(
"assets/${request.url.toString().replaceFirst("my-special-custom-scheme://", "", 0)}");
final response = CustomSchemeResponse(
data: bytes.buffer.asUint8List(),
contentType: "image/svg+xml",
contentEncoding: "utf-8");
return response;
}
return null;
},
)
```
--------------------------------
### Initialize Flutter Widgets Binding in main()
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
This Dart code snippet demonstrates the essential `WidgetsFlutterBinding.ensureInitialized()` call. It must be the first line in your `main()` method if you need to access the binary messenger or initialize plugins before `runApp()` is called, ensuring proper plugin functionality.
```Dart
void main() {
// it should be the first line in main method
WidgetsFlutterBinding.ensureInitialized();
// rest of your app code
runApp(MyApp());
}
```
--------------------------------
### Initialize Flutter Widgets Binding
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/intro
This code snippet demonstrates how to ensure the Flutter Widgets binding is initialized before `runApp()` is called. This is crucial when plugins need to access the binary messenger early in the application lifecycle, such as during their initialization phase.
```Dart
void main() {
// it should be the first line in main method
WidgetsFlutterBinding.ensureInitialized();
// rest of your app code
runApp(MyApp());
}
```
--------------------------------
### Configure Flutter Assets in pubspec.yaml
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
This snippet demonstrates how to declare local asset files (images, JavaScript, CSS, HTML) in the `pubspec.yaml` file to make them accessible to a Flutter application. Assets must be listed under the `flutter: assets:` section to be found and bundled with the app.
```YAML
...
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/index.html
- assets/css/
- assets/images/
...
```
--------------------------------
### Complete Flutter InAppWebView Setup for Handlers
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/webview/javascript/communication
Provides a complete Flutter application structure demonstrating the setup of `InAppWebView` for JavaScript handler communication, including necessary imports, platform-specific debugging, and basic widget structure.
```Dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State {
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("JavaScript Handlers")),
body: SafeArea(
child: Column(children: [
Expanded(
child: InAppWebView(
initialData: InAppWebViewInitialData(
```
--------------------------------
### Flutter InAppLocalhostServer Basic Usage Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/in-app-localhost-server
This comprehensive Flutter example demonstrates how to set up and use InAppLocalhostServer to serve web assets from the 'assets' folder. It shows server initialization, conditional startup based on platform, and integrating the server with InAppWebView to load content from http://localhost:8080/index.html.
```Dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
final InAppLocalhostServer localhostServer =
InAppLocalhostServer(documentRoot: 'assets');
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb) {
// start the localhost server
await localhostServer.start();
}
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('InAppLocalhostServer Example'),
),
body: Container(
child: Column(children: [
Expanded(
child: InAppWebView(
initialSettings: InAppWebViewSettings(
isInspectable: kDebugMode,
),
initialUrlRequest:
URLRequest(url: WebUri("http://localhost:8080/index.html")),
onWebViewCreated: (controller) {},
onLoadStart: (controller, url) {},
onLoadStop: (controller, url) {},
),
)
])),
);
}
}
```
--------------------------------
### Configure Swift Language Version for iOS Podfile
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
Explains how to resolve the "Swift Language Version" build error in iOS projects by modifying the Podfile to set SWIFT_VERSION to '5.0' and ENABLE_BITCODE to 'NO'. This is often required for projects integrating Swift plugins.
```Ruby
target 'Runner' do
use_frameworks! # required by simple_permission
...
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '5.0' # required by simple_permission
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
}
end
```
--------------------------------
### Flutter HeadlessInAppWebView Basic Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/headless-in-app-webview
This Flutter example demonstrates the fundamental usage of `HeadlessInAppWebView`. It initializes a headless WebView, loads a URL, handles `onWebViewCreated`, `onConsoleMessage`, `onLoadStart`, and `onLoadStop` events. It also shows how to run, dispose, and interact with the WebView by evaluating JavaScript, along with managing its lifecycle within a Flutter `StatefulWidget`.
```Dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
HeadlessInAppWebView? headlessWebView;
String url = "";
@override
void initState() {
super.initState();
headlessWebView = HeadlessInAppWebView(
initialUrlRequest: URLRequest(url: WebUri("https://github.com/flutter")),
initialSettings: InAppWebViewSettings(isInspectable: kDebugMode),
onWebViewCreated: (controller) {
const snackBar = SnackBar(
content: Text('HeadlessInAppWebView created!'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onConsoleMessage: (controller, consoleMessage) {
final snackBar = SnackBar(
content: Text('Console Message: ${consoleMessage.message}'),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onLoadStart: (controller, url) async {
final snackBar = SnackBar(
content: Text('onLoadStart $url'),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
setState(() {
this.url = url?.toString() ?? '';
});
},
onLoadStop: (controller, url) async {
final snackBar = SnackBar(
content: Text('onLoadStop $url'),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
setState(() {
this.url = url?.toString() ?? '';
});
},
);
}
@override
void dispose() {
super.dispose();
headlessWebView?.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"HeadlessInAppWebView Example",
)),
body: SafeArea(
child: Column(children: [
Container(
padding: const EdgeInsets.all(20.0),
child: Text(
"URL: ${(url.length > 50) ? "${url.substring(0, 50)}..." : url}"),
),
Center(
child: ElevatedButton(
onPressed: () async {
await headlessWebView?.dispose();
await headlessWebView?.run();
},
child: const Text("Run HeadlessInAppWebView")),
),
Center(
child: ElevatedButton(
onPressed: () async {
if (headlessWebView?.isRunning() ?? false) {
await headlessWebView?.webViewController
?.evaluateJavascript(
source: "console.log('Here is the message!');");
} else {
const snackBar = SnackBar(
content: Text(
'HeadlessInAppWebView is not running. Click on "Run HeadlessInAppWebView"!'),
duration: Duration(milliseconds: 1500),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
child: const Text("Send console.log message")),
),
Center(
child: ElevatedButton(
onPressed: () {
headlessWebView?.dispose();
setState(() {
url = '';
});
},
child: const Text("Dispose HeadlessInAppWebView")),
)
```
--------------------------------
### Full Flutter InAppWebView Print Job Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/print-job-controller
A complete Flutter application example demonstrating the integration of `InAppWebView` with `PrintJobController`. It covers initializing the web view, triggering a print job with custom settings, handling print job completion, and proper disposal of the controller.
```Dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewSettings settings =
InAppWebViewSettings(isInspectable: kDebugMode);
PrintJobController? printJobController;
@override
void dispose() {
// dispose any print job
printJobController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Print Job Controller'),
actions: [
IconButton(
onPressed: () async {
// dispose any previous print job
printJobController?.dispose();
final jobSettings = PrintJobSettings(
handledByClient: true,
jobName:
"${await webViewController?.getTitle() ?? ''} - PDF Document example",
colorMode: PrintJobColorMode.MONOCHROME,
outputType: PrintJobOutputType.GRAYSCALE,
orientation: PrintJobOrientation.LANDSCAPE,
numberOfPages: 1);
printJobController = await webViewController
?.printCurrentPage(settings: jobSettings);
if (defaultTargetPlatform == TargetPlatform.iOS) {
printJobController?.onComplete = (completed, error) async {
if (completed) {
print("Print Job Completed");
} else {
print("Print Job Failed $error");
}
printJobController?.dispose();
};
}
final jobInfo = await printJobController?.getInfo();
print(jobInfo);
},
icon: const Icon(Icons.print))
],
),
body: Column(children: [
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: WebUri("https://github.com/flutter/")),
initialSettings: settings,
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
},
)),
]));
}
}
```
--------------------------------
### Declare Assets in pubspec.yaml for Flutter
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/intro
To make local asset files such as images, JavaScript, or CSS visible and accessible to your Flutter application, you must declare them in the `assets` section of your `pubspec.yaml` file. Failure to do so will prevent Flutter from locating these files at runtime. This example demonstrates how to include an HTML file, a CSS directory, and an images directory.
```YAML
...
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
assets:
- assets/index.html
- assets/css/
- assets/images/
...
```
--------------------------------
### Flutter HeadlessInAppWebView Basic Usage Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/webview/headless-in-app-webview
This comprehensive Flutter example demonstrates how to integrate and manage a `HeadlessInAppWebView`. It initializes the WebView with a URL, handles various lifecycle events like creation, console messages, and page load start/stop. The UI provides buttons to run, send JavaScript messages, and dispose of the headless WebView, showcasing essential interactions and state management.
```Dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(MaterialApp(home: new MyApp()));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State {
HeadlessInAppWebView? headlessWebView;
String url = "";
@override
void initState() {
super.initState();
headlessWebView = new HeadlessInAppWebView(
initialUrlRequest:
URLRequest(url: Uri.parse("https://github.com/flutter")),
onWebViewCreated: (controller) {
final snackBar = SnackBar(
content: Text('HeadlessInAppWebView created!'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onConsoleMessage: (controller, consoleMessage) {
final snackBar = SnackBar(
content: Text('Console Message: ${consoleMessage.message}'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onLoadStart: (controller, url) async {
final snackBar = SnackBar(
content: Text('onLoadStart $url'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
setState(() {
this.url = url?.toString() ?? '';
});
},
onLoadStop: (controller, url) async {
final snackBar = SnackBar(
content: Text('onLoadStop $url'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
setState(() {
this.url = url?.toString() ?? '';
});
},
);
}
@override
void dispose() {
super.dispose();
headlessWebView?.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"HeadlessInAppWebView Example",
)),
body: SafeArea(
child: Column(children: [
Container(
padding: EdgeInsets.all(20.0),
child: Text(
"URL: ${(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 {
if (headlessWebView?.isRunning() ?? false) {
await headlessWebView?.webViewController.evaluateJavascript(
source: "console.log('Here is the message!');");
} else {
final snackBar = SnackBar(
content: Text(
'HeadlessInAppWebView is not running. Click on \"Run HeadlessInAppWebView\"!'),
duration: Duration(milliseconds: 1500),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
child: Text("Send console.log message")),
),
Center(
child: ElevatedButton(
onPressed: () {
headlessWebView?.dispose();
setState(() {
this.url = '';
});
},
child: Text("Dispose HeadlessInAppWebView")),
)
])))
}
}
```
--------------------------------
### Flutter InAppWebView Context Menu Customization Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/context-menu
This Flutter example demonstrates how to customize the `WebView` context menu within an `InAppWebView`. It shows how to add a custom menu item (labeled 'Special'), and how to implement callbacks for `onCreateContextMenu` to display selected text and `onContextMenuActionItemClicked` to react to custom menu item selections. It also includes platform-specific setup for Android debugging and iOS link preview.
```dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewSettings settings =
InAppWebViewSettings(isInspectable: kDebugMode);
late ContextMenu contextMenu;
@override
void initState() {
super.initState();
contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(
id: 1,
title: "Special",
action: () async {
const snackBar = SnackBar(
content: Text("Special clicked!"),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
})
],
onCreateContextMenu: (hitTestResult) async {
String selectedText =
await webViewController?.getSelectedText() ?? "";
final snackBar = SnackBar(
content: Text(
"Selected text: '$selectedText', of type: ${hitTestResult.type.toString()}"),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onContextMenuActionItemClicked: (menuItem) {
final snackBar = SnackBar(
content: Text(
"Menu item with ID ${menuItem.id} and title '${menuItem.title}' clicked!"),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ContextMenu Example'),
),
body: Column(children: [
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest: URLRequest(url: WebUri("https://flutter.dev/")),
contextMenu: contextMenu,
initialSettings: settings,
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
},
))
]));
}
}
```
--------------------------------
### Full Flutter Example with WebViewAssetLoader and Custom Domain
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/webview-asset-loader
This complete Flutter application demonstrates setting up `InAppWebView` with `WebViewAssetLoader` and a custom domain. It includes essential security settings for file access and shows how to load an initial URL from the custom domain, serving assets via the configured asset loader.
```Dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewSettings settings = InAppWebViewSettings(
isInspectable: kDebugMode,
// Setting this off for security. Off by default for SDK versions >= 16.
allowFileAccessFromFileURLs: false,
// Off by default, deprecated for SDK versions >= 30.
allowUniversalAccessFromFileURLs: false,
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
allowFileAccess: false,
allowContentAccess: false,
// Basic WebViewAssetLoader with custom domain
webViewAssetLoader: WebViewAssetLoader(
domain: "my.custom.domain.com",
pathHandlers: [AssetsPathHandler(path: '/assets/')]));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WebView Asset Loader'),
),
body: Column(children: [
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest: URLRequest(
url: WebUri(
"https://my.custom.domain.com/assets/flutter_assets/assets/website/index.html")),
```
--------------------------------
### Request Camera and Microphone Permissions in Flutter (Dart)
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
This Dart code snippet shows how to request camera and optional microphone permissions using the `permission_handler` plugin. Permissions are typically requested at application startup to enable features like taking images or recording audio through HTML inputs within an InAppWebView.
```Dart
import 'package:permission_handler/permission_handler';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Permission.camera.request();
await Permission.microphone.request(); // if you need microphone permission
runApp(MyApp());
}
```
--------------------------------
### Example HTML Asset for Flutter WebView
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/webview-asset-loader
A complete HTML file ('assets/website/index.html') designed to be used as a local asset within a Flutter InAppWebView. It provides a basic structure with a title and a paragraph.
```HTML
WebViewAssetLoader
WebViewAssetLoader
This is a test.
```
--------------------------------
### Configure InAppWebView FileProvider in AndroidManifest.xml
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
This XML snippet shows how to add the `InAppWebViewFileProvider` configuration within the `` tag of `AndroidManifest.xml`. This provider is essential for `flutter_inappwebview` to handle file access, particularly for features like file uploads from HTML inputs, by granting necessary URI permissions.
```XML
```
--------------------------------
### Evaluate JavaScript to Set Up and Dispatch Custom Events from Dart
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/webview/javascript/communication
This example combines setting up a JavaScript event listener and then dispatching a custom event, all initiated from Dart using the `InAppWebViewController.evaluateJavascript` method. This allows dynamic interaction with the web content.
```Dart
onLoadStop: (controller, url) async {
await controller.evaluateJavascript(source: """
window.addEventListener("myCustomEvent", (event) => {
console.log(JSON.stringify(event.detail));
}, false);
""");
await Future.delayed(Duration(seconds: 5));
controller.evaluateJavascript(source: """
const event = new CustomEvent("myCustomEvent", {
detail: {foo: 1, bar: false}
});
window.dispatchEvent(event);
""");
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
// it will print: {message: {"foo":1,"bar":false}, messageLevel: 1}
}
```
--------------------------------
### Configure InAppWebView FileProvider in AndroidManifest.xml
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/intro
To allow the Flutter InAppWebView plugin to access and provide files securely on Android, you must declare the `InAppWebViewFileProvider` within the `` tag of your `AndroidManifest.xml` file. This provider facilitates secure file sharing by defining authorities and granting URI permissions, referencing a `provider_paths` XML resource for path configurations.
```XML
```
--------------------------------
### Flutter InAppWebView Context Menu Customization Example
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/webview/context-menu
This Dart code example demonstrates how to implement a custom context menu for `InAppWebView` in a Flutter application. It shows how to define custom `ContextMenuItem`s, handle the `onCreateContextMenu` event to retrieve selected text, and process clicks on both custom and default menu items using `onContextMenuActionItemClicked`. The example also includes necessary platform-specific initializations.
```Dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(MaterialApp(home: new MyApp()));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
);
late ContextMenu contextMenu;
@override
void initState() {
super.initState();
contextMenu = ContextMenu(
menuItems: [
ContextMenuItem(
androidId: 1,
iosId: "1",
title: "Special",
action: () async {
final snackBar = SnackBar(
content: Text("Special clicked!"),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
})
],
onCreateContextMenu: (hitTestResult) async {
String selectedText =
await webViewController?.getSelectedText() ?? "";
final snackBar = SnackBar(
content: Text(
"Selected text: '$selectedText', of type: ${hitTestResult.type.toString()}"),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onContextMenuActionItemClicked: (menuItem) {
var id = (Platform.isAndroid) ? menuItem.androidId : menuItem.iosId;
final snackBar = SnackBar(
content: Text(
"Menu item with ID $id and title '${menuItem.title}' clicked!"),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ContextMenu Example'),
),
body: Column(children: [
Expanded(
child: InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: Uri.parse("https://flutter.dev/")),
contextMenu: contextMenu,
initialOptions: options,
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
},
)),
]));
}
}
```
--------------------------------
### Convert HeadlessInAppWebView to InAppWebView Widget in Flutter
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/headless-in-app-webview
This Flutter example demonstrates how to initialize a HeadlessInAppWebView with specific settings, a URL request, and a PullToRefreshController. It then shows how to run the headless web view and subsequently convert it into a visible InAppWebView widget by setting a flag, illustrating the process of displaying a previously headless web view.
```Dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
HeadlessInAppWebView? headlessWebView;
PullToRefreshController? pullToRefreshController;
InAppWebViewController? webViewController;
String url = "";
int progress = 0;
bool convertFlag = false;
@override
void initState() {
super.initState();
pullToRefreshController = kIsWeb ||
![TargetPlatform.iOS, TargetPlatform.android]
.contains(defaultTargetPlatform)
? null
: PullToRefreshController(
settings: PullToRefreshSettings(
color: Colors.blue,
),
onRefresh: () async {
if (defaultTargetPlatform == TargetPlatform.android) {
webViewController?.reload();
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
webViewController?.loadUrl(
urlRequest:
URLRequest(url: await webViewController?.getUrl()));
}
},
);
headlessWebView = HeadlessInAppWebView(
initialUrlRequest: URLRequest(url: WebUri("https://flutter.dev")),
initialSettings: InAppWebViewSettings(isInspectable: kDebugMode),
pullToRefreshController: pullToRefreshController,
onWebViewCreated: (controller) {
webViewController = controller;
const snackBar = SnackBar(
content: Text('HeadlessInAppWebView created!'),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
onLoadStart: (controller, url) async {
setState(() {
this.url = url?.toString() ?? '';
});
},
onProgressChanged: (controller, progress) {
setState(() {
this.progress = progress;
});
},
onLoadStop: (controller, url) async {
setState(() {
this.url = url?.toString() ?? '';
});
},
);
}
@override
void dispose() {
super.dispose();
headlessWebView?.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"HeadlessInAppWebView to InAppWebView",
textScaleFactor: .8,
)),
body: Column(children: [
Container(
padding: const EdgeInsets.all(20.0),
child: Text(
"URL: ${(url.length > 40) ? "${url.substring(0, 40)}..." : url} - $progress%"),
),
!convertFlag
? Center(
child: ElevatedButton(
onPressed: () async {
var headlessWebView = this.headlessWebView;
if (headlessWebView != null &&
!headlessWebView.isRunning()) {
await headlessWebView.run();
}
},
child: const Text("Run HeadlessInAppWebView")),
)
: Container(),
!convertFlag
? Center(
child: ElevatedButton(
onPressed: () {
if (!convertFlag) {
setState(() {
convertFlag = true;
});
}
},
```
--------------------------------
### Additional iOS Info.plist App Transport Security Properties
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/intro
This section documents additional useful properties for the `NSAppTransportSecurity` dictionary in the iOS `Info.plist` file. These keys control specific network behaviors related to local resource loading and web view content security.
```APIDOC
NSAppTransportSecurity Properties:
NSAllowsLocalNetworking:
Type: Boolean
Description: A Boolean value indicating whether to allow loading of local resources.
NSAllowsArbitraryLoadsInWebContent:
Type: Boolean
Description: A Boolean value indicating whether all App Transport Security restrictions are disabled for requests made from web views.
```
--------------------------------
### Example of Valid Custom Scheme URL in HTML
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/in-app-webview
This HTML snippet demonstrates using a well-formed custom scheme URL (e.g., 'example-app:') instead of a simple string. This approach ensures consistent handling by WebView and allows for programmatic interception.
```HTML
Show Profile
```
--------------------------------
### Add Camera and Audio Permissions to AndroidManifest.xml
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/intro
This XML snippet provides the necessary permissions to be added to the `AndroidManifest.xml` file on Android. These permissions are required for the application to access the device's camera and microphone for image and video capture, especially when using HTML input types that interact with these device features.
```XML
```
--------------------------------
### Basic InAppWebView Usage in Flutter
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/5.x.x/webview/in-app-webview
This example demonstrates the fundamental setup and control of an InAppWebView widget in a Flutter application. It includes initializing the WebView, handling URL loading, managing permissions, implementing pull-to-refresh, and integrating with the device's default browser for external URLs. It highlights the use of InAppWebViewController and InAppWebViewGroupOptions for cross-platform configuration.
```Dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(MaterialApp(
home: new MyApp()
));
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: false,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
));
late PullToRefreshController pullToRefreshController;
String url = "";
double progress = 0;
final urlController = TextEditingController();
@override
void initState() {
super.initState();
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("Official InAppWebView website")),
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/search?q=" + value);
}
webViewController?.loadUrl(
urlRequest: URLRequest(url: url));
},
),
Expanded(
child: Stack(
children: [
InAppWebView(
key: webViewKey,
initialUrlRequest:
URLRequest(url: Uri.parse("https://inappwebview.dev/")),
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)) {
// Launch the App
await launch(
url,
);
// and cancel the request
return NavigationActionPolicy.CANCEL;
}
}
return NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) async {
pullToRefreshController.endRefreshing();
```
--------------------------------
### Full Flutter Example: Dart-JavaScript Web Message Channel Communication
Source: https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser/webview/javascript/communication
Provides a complete Flutter application demonstrating bidirectional communication using Web Message Channels. The Dart side creates the channel and transfers `port2` to the JavaScript context. The JavaScript side captures the port, sends messages to Dart, and listens for incoming messages. The example also shows how to set up the `InAppWebView` and handle message callbacks.
```Dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State {
InAppWebViewSettings settings = InAppWebViewSettings();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Web Message Channels")),
body: SafeArea(
child: Column(children: [
Expanded(
child: InAppWebView(
initialData: InAppWebViewInitialData(data: """
WebMessageChannel Test
Send