Flutter笔记关于WebView插件的用法(下)
-
文章信息 -
Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSite:http://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/139613391
HuaWei:https://bbs.huaweicloud.com/blogs/428875
【介绍】:WebView是一个可以在移动应用中显示网页的组件。它基于原生的WebView控件(如iOS中的WKWebView和Android中的WebView),提供了加载URL、显示HTML内容、与JavaScript交互等功能。通过在Flutter应用中使用WebView,我们可以方便地集成Web内容,并与之进行交互。本文介绍Flutter中WebView插件的用法。
上一节:《 关于WebView插件的用法(上) 》
目 录
WebView提供了一些自定义选项,可以根据需求对WebView的外观和行为进行定制。下面我们来详细介绍几种常见的自定义WebView的方法。
默认情况下,WebView的背景色是不透明的白色。如果需要实现WebView的透明效果,可以通过设置WebView的背景色为透明来实现。
// 设置WebView背景色为透明
controller.setBackgroundColor(Colors.transparent);
在上面的示例中,通过WebViewController的
setBackgroundColor
方法将WebView的背景色设置为
Colors.transparent
,表示完全透明。
设置透明背景后,WebView的内容将会显示在其下方的Flutter小部件之上。这样可以实现WebView与其他Flutter小部件的叠加和混合效果。
需要注意的是,设置透明背景只会影响WebView的背景色,而不会影响网页内容的背景色。如果网页本身设置了不透明的背景色,那么即使将WebView的背景色设置为透明,网页内容的背景色仍然会保持不透明。
用户代理(User Agent)是一个字符串,用于标识浏览器或客户端的身份和版本信息。WebView默认使用系统提供的用户代理字符串,但有时我们可能需要自定义用户代理以满足特定的需求。
// 自定义用户代理字符串constString userAgent ='MyApp/1.0';await controller.setUserAgent(userAgent);
在上面的示例中,我们定义了一个自定义的用户代理字符串
'MyApp/1.0'
,表示我们的应用名称和版本号。然后通过WebViewController的
setUserAgent
方法将自定义的用户代理字符串设置给WebView。
设置自定义用户代理后,WebView在发送HTTP请求时将使用自定义的用户代理字符串,而不是默认的系统用户代理。这可以用于模拟特定的浏览器或客户端,或者向服务器传递额外的信息。
除了自定义用户代理外,还可以在WebView加载页面时设置自定义的HTTP请求头。这可以用于传递额外的信息给服务器,或者满足某些特殊的请求要求。
// 自定义HTTP请求头await controller.loadRequest(Uri.parse('https://example.com'),
headers:{'X-Custom-Header':'Value','Authorization':'Bearer token',},);
在上面的示例中,通过WebViewController的
loadRequest
方法加载一个网址,并通过
headers
参数设置自定义的HTTP请求头。这里我们设置了两个自定义请求头:
'X-Custom-Header'
和
'Authorization'
,分别传递了一个自定义的值和身份验证的令牌。
设置自定义HTTP请求头后,WebView在发送HTTP请求时将包含这些自定义的请求头。服务器可以根据这些请求头的值来执行相应的操作,如身份验证、数据过滤等。
需要注意的是,并非所有的请求头都可以被自定义。有些请求头是由浏览器或WebView自动添加的,如
'User-Agent'
、
'Referer'
等。尝试自定义这些请求头可能会被浏览器或WebView忽略或覆盖。
通过合理地使用自定义WebView的选项,如透明背景、自定义用户代理和自定义HTTP请求头,可以根据实际需求对WebView的外观和行为进行定制,提供更加灵活和个性化的用户体验。同时,在自定义时也需要注意与目标网站的兼容性和请求头的限制,以确保WebView能够正常工作。
WebView在不同的平台上提供了一些特定的功能和配置选项。下面我们来详细介绍在Android平台上的一些特性。
在Android平台上,WebView提供了一些额外的功能和配置选项,可以根据需求进行定制和控制。
在进行Web开发和调试时,启用WebView的调试模式可以方便地进行调试和问题排查。在Android平台上,可以通过以下方式启用WebView的调试模式:
import'package:webview_flutter_android/webview_flutter_android.dart';// 启用WebView调试模式if(controller.platform isAndroidWebViewController){AndroidWebViewController.enableDebugging(true);}
在上面的示例中,我们首先判断当前的WebView平台是否为AndroidWebViewController。如果是,则通过调用AndroidWebViewController的
enableDebugging
方法,将参数设置为
true
,启用WebView的调试模式。
启用调试模式后,可以通过Chrome开发者工具进行Web开发和调试。在Chrome浏览器中打开
"chrome://inspect"
,可以看到当前连接的Android设备和正在运行的WebView实例。点击对应的WebView实例,即可打开Chrome开发者工具,进行元素审查、控制台调试、网络监控等操作。
需要注意的是,启用调试模式会对性能产生一定的影响,因此在生产环境中应该禁用调试模式。可以通过将
enableDebugging
方法的参数设置为
false
来禁用调试模式。
在Android平台上,WebView默认要求用户手势(如点击)才能触发媒体(如视频、音频)的播放。这是为了防止自动播放媒体对用户体验的影响。但是,在某些情况下,我们可能希望允许WebView自动播放媒体,无需用户手势。可以通过以下方式控制WebView中媒体播放器的行为:
import'package:webview_flutter_android/webview_flutter_android.dart';// 设置媒体播放器不需要用户手势if(controller.platform isAndroidWebViewController){(controller.platform asAndroidWebViewController).setMediaPlaybackRequiresUserGesture(false);}
在上面的示例中,我们首先判断当前的WebView平台是否为AndroidWebViewController。如果是,则通过将AndroidWebViewController的
setMediaPlaybackRequiresUserGesture
方法的参数设置为
false
,来允许WebView自动播放媒体,无需用户手势。
设置
setMediaPlaybackRequiresUserGesture
为
false
后,WebView中的媒体播放器将可以自动开始播放,无需用户的点击或其他交互操作。这在某些场景下可能很有用,如播放背景音乐、自动播放视频等。
需要注意的是,自动播放媒体可能会对用户体验产生负面影响,尤其是在移动设备上,因为它可能会消耗额外的带宽和电量。因此,在决定是否允许自动播放媒体时,需要根据具体的应用场景和用户需求进行权衡。
通过合理地使用Android平台提供的WebView特性,如调试模式和媒体播放控制,可以方便地进行Web开发和调试,以及根据需求定制WebView的行为。这样可以提供更加灵活和优化的用户体验,同时也要注意不同设置可能带来的影响和权衡。
WebView在iOS平台上提供了一些特定的功能和配置选项,可以根据需求进行定制和控制。下面我们来详细介绍在iOS平台上的一些特性。
在iOS平台上,WebView默认不支持内联(inline)的媒体播放,即在网页中嵌入的视频或音频元素无法直接在WebView中播放,而是会跳转到系统的媒体播放器进行播放。如果希望在WebView中实现内联的媒体播放,可以通过以下方式进行配置:
import'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';// 创建WebView控制器时启用内联媒体播放finalWebViewController controller =WebViewController(
initialUrl:'https://example.com',
creationParams:constWebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback:true,),);
在上面的示例中,我们在创建WebViewController时,通过设置
WebKitWebViewControllerCreationParams
的
allowsInlineMediaPlayback
属性为
true
,来启用WebView的内联媒体播放功能。
启用内联媒体播放后,WebView中嵌入的视频或音频元素将可以直接在WebView内部播放,无需跳转到系统的媒体播放器。这样可以提供更加流畅和一致的用户体验。
需要注意的是,启用内联媒体播放可能会对性能和资源消耗产生一定的影响,因为它需要在WebView中加载和渲染媒体内容。因此,在决定是否启用内联媒体播放时,需要根据具体的应用场景和用户需求进行权衡。
在iOS平台上,WebView默认支持通过手势进行页面的前进和后退导航。用户可以通过在WebView中向左或向右滑动来触发页面的前进或后退操作。如果希望禁用WebView的手势导航功能,可以通过以下方式进行配置:
import'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';// 禁用WebView的手势导航if(controller.platform isWebKitWebViewController){(controller.platform asWebKitWebViewController).setAllowsBackForwardNavigationGestures(false);}
在上面的示例中,我们首先判断当前的WebView平台是否为
WebKitWebViewController
。如果是,则通过将
WebKitWebViewController
的
setAllowsBackForwardNavigationGestures
方法的参数设置为
false
,来禁用WebView的手势导航功能。
禁用手势导航后,用户将无法通过在WebView中滑动来触发页面的前进或后退操作。这在某些场景下可能很有用,例如当你希望完全控制页面导航行为,或者想要避免用户意外触发导航操作时。
需要注意的是,禁用手势导航并不会影响其他的导航方式,如通过代码调用
goBack
或
goForward
方法,或者点击网页中的链接进行导航。它只是禁用了通过手势触发的导航操作。
通过合理地使用 iOS平台提供的WebView特性,如内联媒体播放和手势导航控制,可以根据需求定制WebView的行为,提供更加优化和个性化的用户体验。同时也要注意不同设置可能带来的影响和权衡,以确保WebView的性能和功能符合应用的要求。
WebView提供了一种监听控制台日志输出的机制,可以捕获网页中的
console.log
、
console.warn
、
console.error
等日志信息,并在Flutter应用中进行打印和处理。这对于调试和监控WebView中的JavaScript代码非常有帮助。
下面是一个示例,演示如何监听WebView的控制台日志输出,并在Flutter应用中进行打印:
import'package:webview_flutter/webview_flutter.dart';// ...// 创建WebView控制器finalWebViewController controller =WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..setNavigationDelegate(NavigationDelegate(
onPageStarted:(String url){// 页面开始加载时添加JavaScript日志监听
controller.runJavaScript('''
console.log = function(message) {
window.flutter_inappwebview.callHandler('consoleLog', message);
};
console.warn = function(message) {
window.flutter_inappwebview.callHandler('consoleWarn', message);
};
console.error = function(message) {
window.flutter_inappwebview.callHandler('consoleError', message);
};
''');},),)..addJavaScriptChannel('flutter_inappwebview',
onMessageReceived:(JavaScriptMessage message){// 处理JavaScript日志消息switch(message.message){case'consoleLog':print('WebView Console Log: ${message.arguments}');break;case'consoleWarn':print('WebView Console Warn: ${message.arguments}');break;case'consoleError':print('WebView Console Error: ${message.arguments}');break;}},)..loadRequest(Uri.parse('https://example.com'));// ...
在上面的示例中,我们通过
setNavigationDelegate
设置了一个NavigationDelegate,并在
onPageStarted
回调中添加了JavaScript日志监听。
我们使用
runJavaScript
方法向WebView注入了一段JavaScript代码,重写了
console.log
、
console.warn
和
console.error
方法。当网页中调用这些方法时,会通过
window.flutter_inappwebview.callHandler
方法将日志消息发送给Flutter应用。
接着,我们通过
addJavaScriptChannel
添加了一个名为
flutter_inappwebview
的JavaScript通道,并在
onMessageReceived
回调中处理接收到的JavaScript日志消息。
根据消息的内容,我们可以判断是
consoleLog
、
consoleWarn
还是
consoleError
,并相应地进行打印和处理。例如,对于
consoleLog
消息,我们使用
print
语句将日志内容打印到控制台。
通过这种方式,我们就可以实时监听WebView中的控制台日志输出,并在Flutter应用中进行打印和处理。这对于调试和监控WebView中的JavaScript代码非常有帮助,可以方便地查看日志信息,定位问题,并进行相应的处理。
需要注意的是,由于JavaScript日志消息是通过JavaScript通道传递的,因此需要确保WebView已经加载完成,并且JavaScript环境已经准备就绪,才能正确地捕获和处理日志消息。可以在
onPageFinished
回调中添加相应的逻辑,以确保日志监听功能的正常工作。
另外,在处理JavaScript日志消息时,还可以根据需要进行过滤、格式化或存储等操作,以满足不同的调试和监控需求。例如,可以将日志消息写入文件、上传到服务器或与其他调试工具集成,以便进行更全面的分析和追踪。
在WebView加载页面时,如果遇到需要HTTP认证的请求,可以通过NavigationDelegate的
onHttpAuthRequest
回调来处理认证请求。
下面的例子,展示如何处理WebView的HTTP认证请求:
import'package:webview_flutter/webview_flutter.dart';// ...// 创建WebView控制器finalWebViewController controller =WebViewController()..setNavigationDelegate(NavigationDelegate(
onHttpAuthRequest:(HttpAuthRequest request)async{// 处理HTTP认证请求if(request.host =='example.com'){// 提示用户输入凭据finalString username =await_showUsernameDialog();finalString password =await_showPasswordDialog();// 返回认证凭据returnHttpAuthResponse(
username: username,
password: password,
action:HttpAuthResponseAction.proceed,);}else{// 取消认证请求returnHttpAuthResponse(
action:HttpAuthResponseAction.cancel,);}},),)..loadRequest(Uri.parse('https://example.com'));// ...// 显示用户名输入对话框Future<String>_showUsernameDialog()async{// 实现用户名输入对话框的逻辑// ...}// 显示密码输入对话框Future<String>_showPasswordDialog()async{// 实现密码输入对话框的逻辑// ...}
这里,我们通过
setNavigationDelegate
设置了一个NavigationDelegate,并实现了onHttpAuthRequest回调。
当WebView遇到需要HTTP认证的请求时,会触发
onHttpAuthRequest
回调,并传递一个HttpAuthRequest对象,其中包含了认证请求的相关信息,如主机(host)、领域(realm)等。
在
onHttpAuthRequest
回调中,我们可以根据请求的主机或其他条件来决定是否处理认证请求。例如,在示例中,我们只处理主机为
'example.com'
的认证请求。
如果决定处理认证请求,可以提示用户输入凭据(如用户名和密码)。这里我们使用了两个自定义的函数_showUsernameDialog和_showPasswordDialog来显示用户名和密码的输入对话框,并获取用户输入的值。
获取到用户输入的凭据后,我们可以通过返回一个
HttpAuthResponse
对象来提供认证凭据。在
HttpAuthResponse
中,我们设置了用户名(
username
)和密码(
password
),并将
action
属性设置为
HttpAuthResponseAction.proceed
,表示继续进行认证。
如果决定取消认证请求,可以返回一个
HttpAuthResponse
对象,并将
action
属性设置为
HttpAuthResponseAction.cancel
,表示取消认证请求。
需要注意的是,
onHttpAuthRequest
回调是异步的,因此我们使用
async
和
await
来处理异步操作,如显示输入对话框和获取用户输入的值。
另外,在处理HTTP认证请求时,还需要考虑安全性和用户体验。应该根据具体的应用场景和安全要求,选择合适的认证方式和交互流程。例如,可以使用安全的认证协议(如HTTPS)、提供明确的用户提示和反馈、限制认证尝试次数等,以保护用户的凭据和隐私。
通过合理地处理WebView的HTTP认证请求,可以实现对受保护资源的访问控制,提高应用的安全性和用户体验。同时,也要注意处理认证请求时的异步性和错误处理,以确保应用的稳定性和可靠性。
在WebView中进行文件上传和下载时,需要进行一些特殊的处理和配置,以确保文件的正确传输和用户体验。下面我们分别介绍文件上传和下载的处理方式和注意事项。
当WebView加载的网页包含文件上传功能时,可以通过以下步骤来处理文件上传。
1. 配置WebView的文件上传权限
在Android平台上,需要在
AndroidManifest.xml
文件中添加文件读取权限,以允许WebView访问设备上的文件:
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>
在iOS平台上,需要在
Info.plist
文件中添加文件访问权限,以允许WebView访问应用沙盒中的文件:
<key>NSAppTransportSecurity</key><dict><key>NSAllowsArbitraryLoads</key><true/></dict>
2. 实现文件选择回调
当网页中触发文件选择操作时,WebView会调用文件选择回调。可以通过实现WebChromeClient的
onShowFileChooser
方法来处理文件选择回调:
import'package:webview_flutter/webview_flutter.dart';// ...finalWebViewController controller =WebViewController()..setWebChromeClient(WebChromeClient(
onShowFileChooser:(WebViewController controller,FileChooserParams params)async{// 处理文件选择回调finalList<String> acceptedTypes = params.acceptTypes;final bool allowMultiple = params.mode ==FileChooserMode.openMultiple;// 使用文件选择器让用户选择文件finalList<String> selectedFiles =await_showFilePicker(acceptedTypes, allowMultiple);// 将选择的文件路径返回给WebViewreturn selectedFiles;},),);// ...// 显示文件选择器Future<List<String>>_showFilePicker(List<String> acceptedTypes, bool allowMultiple)async{// 实现文件选择器的逻辑// ...}
在
onShowFileChooser
回调中,可以获取文件选择的相关参数,如接受的文件类型(
acceptedTypes
)和是否允许多选(
allowMultiple
)。然后,可以使用文件选择器(如文件管理器或自定义的文件选择器)让用户选择文件。
选择文件后,将选择的文件路径作为List<String>返回给WebView,WebView会自动将这些文件上传到服务器。
需要注意的是,文件选择器的实现方式可能因平台而异。在Android平台上,可以使用Intent和ActivityResultLauncher来启动文件选择器并获取选择的文件路径。在iOS平台上,可以使用UIDocumentPickerViewController来显示文件选择器并获取选择的文件URL。
当WebView加载的网页触发文件下载时,可以通过以下步骤来处理文件下载:
1. 实现下载监听器
可以通过实现WebViewClient的
onDownloadStart
方法来监听文件下载事件:
import'package:webview_flutter/webview_flutter.dart';// ...finalWebViewController controller =WebViewController()..setWebViewClient(WebViewClient(
onDownloadStart:(String url,String userAgent,String contentDisposition,String mimetype, int contentLength){// 处理文件下载_startDownload(url, contentDisposition, mimetype);},),);// ...// 开始下载文件void_startDownload(String url,String contentDisposition,String mimetype)async{// 实现文件下载的逻辑// ...}
在
onDownloadStart
回调中,可以获取下载文件的相关信息,如下载地址(
url
)、文件名(
contentDisposition
)、文件类型(
mimetype
)等。然后,可以使用这些信息来开始文件下载。
2. 请求下载权限(Android)
在Android平台上,需要请求文件写入权限,以允许WebView将文件保存到设备上。可以在AndroidManifest.xml文件中添加以下权限:
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
此外,还需要在运行时动态请求文件写入权限。可以使用
permission_handler
插件来简化权限请求的过程:
import'package:permission_handler/permission_handler.dart';// ...// 请求文件写入权限Future<bool>_requestWritePermission()async{finalPermissionStatus status =awaitPermission.storage.request();return status ==PermissionStatus.granted;}
3. 下载文件
获得必要的权限后,可以使用
http
或
dio
等网络库来下载文件。下面是一个使用
http
库下载文件的示例:
import'package:http/http.dart'as http;import'package:path_provider/path_provider.dart';import'dart:io';// ...// 开始下载文件void_startDownload(String url,String contentDisposition,String mimetype)async{// 请求文件写入权限(Android)if(Platform.isAndroid){final bool hasPermission =await_requestWritePermission();if(!hasPermission){// 没有文件写入权限,取消下载return;}}// 创建下载目录finalDirectory directory =awaitgetApplicationDocumentsDirectory();finalString filePath ='${directory.path}/${_getFileNameFromContentDisposition(contentDisposition)}';// 发起下载请求finalhttp.Response response =await http.get(Uri.parse(url));// 将下载的文件写入本地finalFile file =File(filePath);await file.writeAsBytes(response.bodyBytes);// 通知用户下载完成_showDownloadCompleteNotification(filePath);}// 从Content-Disposition头中提取文件名String_getFileNameFromContentDisposition(String contentDisposition){// 实现从Content-Disposition头中提取文件名的逻辑// ...}// 显示下载完成通知void_showDownloadCompleteNotification(String filePath){// 实现显示下载完成通知的逻辑// ...}
在
_startDownload
方法中,首先判断是否有文件写入权限(Android平台)。如果没有权限,则取消下载。
然后,使用
path_provider
插件获取应用的文档目录,并根据
Content-Disposition
头中的文件名生成本地文件路径。
接着,使用
http
库发起下载请求,并将下载的文件写入本地文件系统。
最后,可以显示一个下载完成的通知,提示用户文件已成功下载。
需要注意的是,在处理文件下载时,还需要考虑以下几点:
- 错误处理:下载过程中可能会出现网络错误、文件写入错误等异常情况,需要进行适当的错误处理和用户提示。
- 下载进度:对于大文件的下载,可以显示下载进度,以提供更好的用户体验。可以通过监听下载进度事件来实现。
- 下载管理:如果应用支持多个文件同时下载,可以实现一个下载管理器,用于管理和跟踪所有的下载任务。
通过合理地处理WebView的文件下载,可以为用户提供方便的文件下载功能,同时确保下载过程的稳定性和可靠性。
版权归原作者 jcLee95 所有, 如有侵权,请联系我们删除。