added onDownloadStartRequest event

This commit is contained in:
Lorenzo Pichilli 2022-04-17 16:19:31 +02:00
parent 1e287fd1d3
commit 22649342e8
14 changed files with 352 additions and 47 deletions

View File

@ -3,6 +3,8 @@
- `getOriginalUrl` method is cross-platform now
- Updated Android `compileSdkVersion` to 31
- Added `singleInstance` option for Android `ChromeSafariBrowser` implementation
- Added `onDownloadStartRequest` event and deprecated old `onDownloadStart` event
- Fixed missing `onZoomScaleChanged` call for `InAppBrowser` class
- Fixed `requestImageRef` method always `null` on iOS
- Fixed "applicationNameForUserAgent is not work in ios" [#525](https://github.com/pichillilorenzo/flutter_inappwebview/issues/525)
- Fixed "Crash when try select file from webview input on Android" [#867](https://github.com/pichillilorenzo/flutter_inappwebview/issues/867)

View File

@ -37,6 +37,7 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
import android.webkit.WebBackForwardList;
import android.webkit.WebHistoryItem;
@ -54,6 +55,7 @@ import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.DownloadStartRequest;
import com.pichillilorenzo.flutter_inappwebview.types.InAppWebViewInterface;
import com.pichillilorenzo.flutter_inappwebview.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappwebview.R;
@ -1181,14 +1183,17 @@ final public class InAppWebView extends InputAwareWebView implements InAppWebVie
class DownloadStartListener implements DownloadListener {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Map<String, Object> obj = new HashMap<>();
obj.put("url", url);
obj.put("userAgent", userAgent);
obj.put("contentDisposition", contentDisposition);
obj.put("mimetype", mimetype);
obj.put("contentLength", contentLength);
channel.invokeMethod("onDownloadStart", obj);
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
DownloadStartRequest downloadStartRequest = new DownloadStartRequest(
url,
userAgent,
contentDisposition,
mimeType,
contentLength,
URLUtil.guessFileName(url, contentDisposition, mimeType),
null
);
channel.invokeMethod("onDownloadStartRequest", downloadStartRequest.toMap());
}
}

View File

@ -0,0 +1,150 @@
package com.pichillilorenzo.flutter_inappwebview.types;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
public class DownloadStartRequest {
@NonNull
private String url;
@NonNull
private String userAgent;
@NonNull
private String contentDisposition;
@NonNull
private String mimeType;
private long contentLength;
@Nullable
private String suggestedFilename;
@Nullable
private String textEncodingName;
public DownloadStartRequest(@NonNull String url, @NonNull String userAgent, @NonNull String contentDisposition, @NonNull String mimeType, long contentLength, @Nullable String suggestedFilename, @Nullable String textEncodingName) {
this.url = url;
this.userAgent = userAgent;
this.contentDisposition = contentDisposition;
this.mimeType = mimeType;
this.contentLength = contentLength;
this.suggestedFilename = suggestedFilename;
this.textEncodingName = textEncodingName;
}
public Map<String, Object> toMap() {
Map<String, Object> obj = new HashMap<>();
obj.put("url", url);
obj.put("userAgent", userAgent);
obj.put("contentDisposition", contentDisposition);
obj.put("mimeType", mimeType);
obj.put("contentLength", contentLength);
obj.put("suggestedFilename", suggestedFilename);
obj.put("textEncodingName", textEncodingName);
return obj;
}
@NonNull
public String getUrl() {
return url;
}
public void setUrl(@NonNull String url) {
this.url = url;
}
@NonNull
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(@NonNull String userAgent) {
this.userAgent = userAgent;
}
@NonNull
public String getContentDisposition() {
return contentDisposition;
}
public void setContentDisposition(@NonNull String contentDisposition) {
this.contentDisposition = contentDisposition;
}
@NonNull
public String getMimeType() {
return mimeType;
}
public void setMimeType(@NonNull String mimeType) {
this.mimeType = mimeType;
}
public long getContentLength() {
return contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
@Nullable
public String getSuggestedFilename() {
return suggestedFilename;
}
public void setSuggestedFilename(@Nullable String suggestedFilename) {
this.suggestedFilename = suggestedFilename;
}
@Nullable
public String getTextEncodingName() {
return textEncodingName;
}
public void setTextEncodingName(@Nullable String textEncodingName) {
this.textEncodingName = textEncodingName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DownloadStartRequest that = (DownloadStartRequest) o;
if (contentLength != that.contentLength) return false;
if (!url.equals(that.url)) return false;
if (!userAgent.equals(that.userAgent)) return false;
if (!contentDisposition.equals(that.contentDisposition)) return false;
if (!mimeType.equals(that.mimeType)) return false;
if (suggestedFilename != null ? !suggestedFilename.equals(that.suggestedFilename) : that.suggestedFilename != null)
return false;
return textEncodingName != null ? textEncodingName.equals(that.textEncodingName) : that.textEncodingName == null;
}
@Override
public int hashCode() {
int result = url.hashCode();
result = 31 * result + userAgent.hashCode();
result = 31 * result + contentDisposition.hashCode();
result = 31 * result + mimeType.hashCode();
result = 31 * result + (int) (contentLength ^ (contentLength >>> 32));
result = 31 * result + (suggestedFilename != null ? suggestedFilename.hashCode() : 0);
result = 31 * result + (textEncodingName != null ? textEncodingName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "DownloadStartRequest{" +
"url='" + url + '\'' +
", userAgent='" + userAgent + '\'' +
", contentDisposition='" + contentDisposition + '\'' +
", mimeType='" + mimeType + '\'' +
", contentLength=" + contentLength +
", suggestedFilename='" + suggestedFilename + '\'' +
", textEncodingName='" + textEncodingName + '\'' +
'}';
}
}

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2022-04-16 12:29:54.757036","version":"2.10.4"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/fvm/versions/2.10.4/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2022-04-17 16:15:55.135230","version":"2.10.4"}

View File

@ -2705,7 +2705,7 @@ void main() {
expect(numberOfMatches, 2);
});
testWidgets('onDownloadStart', (WidgetTester tester) async {
testWidgets('onDownloadStartRequest', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<String> onDownloadStartCompleter = Completer<String>();
await tester.pumpWidget(
@ -2739,8 +2739,8 @@ void main() {
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onDownloadStart:(controller, url, userAgent, contentDisposition, mimeType, contentLength) {
onDownloadStartCompleter.complete(url.toString());
onDownloadStartRequest: (controller, request) {
onDownloadStartCompleter.complete(request.url.toString());
},
),
),

View File

@ -24,7 +24,8 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: false
mediaPlaybackRequiresUserGesture: false,
useOnDownloadStart: true
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
@ -123,7 +124,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
key: webViewKey,
// contextMenu: contextMenu,
initialUrlRequest:
URLRequest(url: Uri.parse("https://github.com/flutter")),
URLRequest(url: Uri.parse("https://testfiledownload.com/")),
// initialFile: "assets/index.html",
initialUserScripts: UnmodifiableListView<UserScript>([]),
initialOptions: options,
@ -131,6 +132,9 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
onWebViewCreated: (controller) {
webViewController = controller;
},
onDownloadStartRequest: (controller, request) {
print(request);
},
onLoadStart: (controller, url) {
setState(() {
this.url = url.toString();

View File

@ -1546,7 +1546,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
let mimeType = navigationResponse.response.mimeType
if let url = navigationResponse.response.url, navigationResponse.isForMainFrame {
if url.scheme != "file", mimeType != nil, !mimeType!.starts(with: "text/") {
onDownloadStart(url: url.absoluteString)
let downloadStartRequest = DownloadStartRequest(url: url.absoluteString,
userAgent: nil,
contentDisposition: nil,
mimeType: mimeType,
contentLength: navigationResponse.response.expectedContentLength,
suggestedFilename: navigationResponse.response.suggestedFilename,
textEncodingName: navigationResponse.response.textEncodingName)
onDownloadStartRequest(request: downloadStartRequest)
if useOnNavigationResponse == nil || !useOnNavigationResponse! {
decisionHandler(.cancel)
}
@ -2363,9 +2370,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
channel?.invokeMethod("onOverScrolled", arguments: arguments)
}
public func onDownloadStart(url: String) {
let arguments: [String: Any] = ["url": url]
channel?.invokeMethod("onDownloadStart", arguments: arguments)
public func onDownloadStartRequest(request: DownloadStartRequest) {
channel?.invokeMethod("onDownloadStartRequest", arguments: request.toMap())
}
public func onLoadResourceCustomScheme(url: String, result: FlutterResult?) {

View File

@ -0,0 +1,42 @@
//
// DownloadStartRequest.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 17/04/22.
//
import Foundation
public class DownloadStartRequest: NSObject {
var url: String
var userAgent: String?
var contentDisposition: String?
var mimeType: String?
var contentLength: Int64
var suggestedFilename: String?
var textEncodingName: String?
public init(url: String, userAgent: String?, contentDisposition: String?,
mimeType: String?, contentLength: Int64,
suggestedFilename: String?, textEncodingName: String?) {
self.url = url
self.userAgent = userAgent
self.contentDisposition = contentDisposition
self.mimeType = mimeType
self.contentLength = contentLength
self.suggestedFilename = suggestedFilename
self.textEncodingName = textEncodingName
}
public func toMap () -> [String:Any?] {
return [
"url": url,
"userAgent": userAgent,
"contentDisposition": contentDisposition,
"mimeType": mimeType,
"contentLength": contentLength,
"suggestedFilename": suggestedFilename,
"textEncodingName": textEncodingName
]
}
}

View File

@ -377,16 +377,21 @@ class InAppBrowser {
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll
void onScrollChanged(int x, int y) {}
///Event fired when [InAppBrowser] recognizes and starts a downloadable file.
///Use [onDownloadStartRequest] instead
@Deprecated('Use `onDownloadStartRequest` instead')
void onDownloadStart(Uri url) {}
///Event fired when [WebView] recognizes a downloadable file.
///To download the file, you can use the [flutter_downloader](https://pub.dev/packages/flutter_downloader) plugin.
///
///[url] represents the url of the file.
///[downloadStartRequest] represents the request of the file to download.
///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
void onDownloadStart(Uri url, String userAgent, String contentDisposition, String mimeType, int contentLength) {}
void onDownloadStartRequest(DownloadStartRequest downloadStartRequest) {}
///Event fired when the [InAppBrowser] webview finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
///

View File

@ -64,7 +64,8 @@ class HeadlessInAppWebView implements WebView {
this.shouldOverrideUrlLoading,
this.onLoadResource,
this.onScrollChanged,
this.onDownloadStart,
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
this.onDownloadStartRequest,
this.onLoadResourceCustomScheme,
this.onCreateWindow,
this.onCloseWindow,
@ -301,14 +302,15 @@ class HeadlessInAppWebView implements WebView {
@override
void Function(InAppWebViewController controller)? onWindowBlur;
///Use [onDownloadStartRequest] instead
@Deprecated('Use `onDownloadStartRequest` instead')
@override
void Function(
InAppWebViewController controller,
Uri url,
String userAgent,
String contentDisposition,
String mimeType,
int contentLength)? onDownloadStart;
final void Function(InAppWebViewController controller, Uri url)?
onDownloadStart;
@override
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
onDownloadStartRequest;
@override
void Function(InAppWebViewController controller, int activeMatchOrdinal,

View File

@ -53,7 +53,8 @@ class InAppWebView extends StatefulWidget implements WebView {
this.shouldOverrideUrlLoading,
this.onLoadResource,
this.onScrollChanged,
this.onDownloadStart,
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
this.onDownloadStartRequest,
this.onLoadResourceCustomScheme,
this.onCreateWindow,
this.onCloseWindow,
@ -211,10 +212,16 @@ class InAppWebView extends StatefulWidget implements WebView {
InAppWebViewController controller, Uri url, bool precomposed)?
androidOnReceivedTouchIconUrl;
///Use [onDownloadStartRequest] instead
@Deprecated('Use `onDownloadStartRequest` instead')
@override
final void Function(InAppWebViewController controller, Uri url, String userAgent, String contentDisposition, String mimeType, int contentLength)?
final void Function(InAppWebViewController controller, Uri url)?
onDownloadStart;
@override
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
onDownloadStartRequest;
@override
final void Function(InAppWebViewController controller, int activeMatchOrdinal,
int numberOfMatches, bool isDoneCounting)? onFindResultReceived;

View File

@ -201,20 +201,26 @@ class InAppWebViewController {
_inAppBrowser!.onScrollChanged(x, y);
}
break;
case "onDownloadStart":
if ((_webview != null && _webview!.onDownloadStart != null) ||
case "onDownloadStartRequest":
if ((_webview != null &&
// ignore: deprecated_member_use_from_same_package
(_webview!.onDownloadStart != null || _webview!.onDownloadStartRequest != null)) ||
_inAppBrowser != null) {
String url = call.arguments["url"];
String userAgent = call.arguments["userAgent"];
String contentDisposition = call.arguments["contentDisposition"];
String mimeType = call.arguments["mimetype"];
int contentLength = call.arguments["contentLength"] as int;
Uri uri = Uri.parse(url);
Map<String, dynamic> arguments = call.arguments.cast<String, dynamic>();
DownloadStartRequest downloadStartRequest = DownloadStartRequest.fromMap(arguments)!;
if (_webview != null && _webview!.onDownloadStart != null)
_webview!.onDownloadStart!(this, uri, userAgent, contentDisposition, mimeType, contentLength);
else
_inAppBrowser!.onDownloadStart(uri, userAgent, contentDisposition, mimeType, contentLength);
if (_webview != null) {
if (_webview!.onDownloadStartRequest != null)
_webview!.onDownloadStartRequest!(this, downloadStartRequest);
else {
// ignore: deprecated_member_use_from_same_package
_webview!.onDownloadStart!(this, downloadStartRequest.url);
}
} else {
// ignore: deprecated_member_use_from_same_package
_inAppBrowser!.onDownloadStart(downloadStartRequest.url);
_inAppBrowser!.onDownloadStartRequest(downloadStartRequest);
}
}
break;
case "onLoadResourceCustomScheme":
@ -380,6 +386,7 @@ class InAppWebViewController {
} else {
// ignore: deprecated_member_use_from_same_package
_inAppBrowser!.androidOnScaleChanged(oldScale, newScale);
_inAppBrowser!.onZoomScaleChanged(oldScale, newScale);
}
}
break;

View File

@ -112,18 +112,23 @@ abstract class WebView {
final void Function(InAppWebViewController controller, int x, int y)?
onScrollChanged;
///Use [onDownloadStartRequest] instead
@Deprecated('Use `onDownloadStartRequest` instead')
final void Function(InAppWebViewController controller, Uri url)?
onDownloadStart;
///Event fired when [WebView] recognizes a downloadable file.
///To download the file, you can use the [flutter_downloader](https://pub.dev/packages/flutter_downloader) plugin.
///
///[url] represents the url of the file.
///[downloadStartRequest] represents the request of the file to download.
///
///**NOTE**: In order to be able to listen this event, you need to set [InAppWebViewOptions.useOnDownloadStart] option to `true`.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#setDownloadListener(android.webkit.DownloadListener)
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455643-webview
final void Function(InAppWebViewController controller, Uri url, String userAgent, String contentDisposition, String mimeType, int contentLength)?
onDownloadStart;
final void Function(InAppWebViewController controller, DownloadStartRequest downloadStartRequest)?
onDownloadStartRequest;
///Event fired when the [WebView] finds the `custom-scheme` while loading a resource. Here you can handle the url request and return a [CustomSchemeResponse] to load a specific resource encoded to `base64`.
///
@ -696,7 +701,8 @@ abstract class WebView {
this.shouldOverrideUrlLoading,
this.onLoadResource,
this.onScrollChanged,
this.onDownloadStart,
@Deprecated('Use `onDownloadStartRequest` instead') this.onDownloadStart,
this.onDownloadStartRequest,
this.onLoadResourceCustomScheme,
this.onCreateWindow,
this.onCloseWindow,

View File

@ -6891,4 +6891,73 @@ class WebViewImplementation {
@override
int get hashCode => _value.hashCode;
}
///Class representing a download request of the WebView used by the event [WebView.onDownloadStartRequest].
class DownloadStartRequest {
///The full url to the content that should be downloaded.
Uri url;
///the user agent to be used for the download.
String? userAgent;
///Content-disposition http header, if present.
String? contentDisposition;
///The mimetype of the content reported by the server.
String? mimeType;
///The file size reported by the server.
int contentLength;
///A suggested filename to use if saving the resource to disk.
String? suggestedFilename;
///The name of the text encoding of the receiver, or `null` if no text encoding was specified.
String? textEncodingName;
DownloadStartRequest(
{required this.url,
this.userAgent,
this.contentDisposition,
this.mimeType,
required this.contentLength,
this.suggestedFilename,
this.textEncodingName});
static DownloadStartRequest? fromMap(Map<String, dynamic>? map) {
if (map == null) {
return null;
}
return DownloadStartRequest(
url: Uri.parse(map["url"]),
userAgent: map["userAgent"],
contentDisposition: map["contentDisposition"],
mimeType: map["mimeType"],
contentLength: map["contentLength"],
suggestedFilename: map["suggestedFilename"],
textEncodingName: map["textEncodingName"]);
}
Map<String, dynamic> toMap() {
return {
"url": url.toString(),
"userAgent": userAgent,
"contentDisposition": contentDisposition,
"mimeType": mimeType,
"contentLength": contentLength,
"suggestedFilename": suggestedFilename,
"textEncodingName": textEncodingName
};
}
Map<String, dynamic> toJson() {
return this.toMap();
}
@override
String toString() {
return toMap().toString();
}
}