diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index f4bc8c32b3d0..8b71eb19c3a7 100644 --- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -122,6 +122,12 @@ public void onMethodCall(MethodCall methodCall, Result result) { case "loadUrl": loadUrl(methodCall, result); break; + case "loadAssetHtmlFile": + loadAssetHtmlFile(methodCall, result); + break; + case "loadLocalHtmlFile": + loadLocalHtmlFile(methodCall, result); + break; case "updateSettings": updateSettings(methodCall, result); break; @@ -175,6 +181,18 @@ private void loadUrl(MethodCall methodCall, Result result) { result.success(null); } + private void loadAssetHtmlFile(MethodCall methodCall, Result result) { + String url = (String) methodCall.arguments; + webView.loadUrl("file:///android_asset/flutter_assets/" + url); + result.success(null); + } + + private void loadLocalHtmlFile(MethodCall methodCall, Result result) { + String url = (String) methodCall.arguments; + webView.loadUrl("file:///" + url); + result.success(null); + } + private void canGoBack(Result result) { result.success(webView.canGoBack()); } diff --git a/packages/webview_flutter/ios/Classes/FLTWebViewFlutterPlugin.m b/packages/webview_flutter/ios/Classes/FLTWebViewFlutterPlugin.m index a131263c9a92..33c29376f267 100644 --- a/packages/webview_flutter/ios/Classes/FLTWebViewFlutterPlugin.m +++ b/packages/webview_flutter/ios/Classes/FLTWebViewFlutterPlugin.m @@ -9,8 +9,7 @@ @implementation FLTWebViewFlutterPlugin + (void)registerWithRegistrar:(NSObject*)registrar { - FLTWebViewFactory* webviewFactory = - [[FLTWebViewFactory alloc] initWithMessenger:registrar.messenger]; + FLTWebViewFactory* webviewFactory = [[FLTWebViewFactory alloc] initWithRegistrar:registrar]; [registrar registerViewFactory:webviewFactory withId:@"plugins.flutter.io/webview"]; [FLTCookieManager registerWithRegistrar:registrar]; } diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.h b/packages/webview_flutter/ios/Classes/FlutterWebView.h index 875551d3535d..8a0205d28c1b 100644 --- a/packages/webview_flutter/ios/Classes/FlutterWebView.h +++ b/packages/webview_flutter/ios/Classes/FlutterWebView.h @@ -12,13 +12,13 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args - binaryMessenger:(NSObject*)messenger; + registrar:(NSObject*)registrar; - (UIView*)view; @end @interface FLTWebViewFactory : NSObject -- (instancetype)initWithMessenger:(NSObject*)messenger; +- (instancetype)initWithRegistrar:(NSObject*)registrar; @end /** diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.m b/packages/webview_flutter/ios/Classes/FlutterWebView.m index 5e3456d50e49..c8534c48b875 100644 --- a/packages/webview_flutter/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/ios/Classes/FlutterWebView.m @@ -8,12 +8,14 @@ @implementation FLTWebViewFactory { NSObject* _messenger; + NSObject* _registrar; } -- (instancetype)initWithMessenger:(NSObject*)messenger { +- (instancetype)initWithRegistrar:(NSObject*)registrar { self = [super init]; if (self) { - _messenger = messenger; + _registrar = registrar; + _messenger = registrar.messenger; } return self; } @@ -28,7 +30,7 @@ - (instancetype)initWithMessenger:(NSObject*)messenger { FLTWebViewController* webviewController = [[FLTWebViewController alloc] initWithFrame:frame viewIdentifier:viewId arguments:args - binaryMessenger:_messenger]; + registrar:_registrar]; return webviewController; } @@ -64,17 +66,19 @@ @implementation FLTWebViewController { // The set of registered JavaScript channel names. NSMutableSet* _javaScriptChannelNames; FLTWKNavigationDelegate* _navigationDelegate; + NSObject* _registrar; } - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args - binaryMessenger:(NSObject*)messenger { + registrar:(nonnull NSObject*)registrar { if (self = [super init]) { _viewId = viewId; - + _registrar = registrar; NSString* channelName = [NSString stringWithFormat:@"plugins.flutter.io/webview_%lld", viewId]; - _channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger]; + _channel = [FlutterMethodChannel methodChannelWithName:channelName + binaryMessenger:_registrar.messenger]; _javaScriptChannelNames = [[NSMutableSet alloc] init]; WKUserContentController* userContentController = [[WKUserContentController alloc] init]; @@ -128,6 +132,10 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self onUpdateSettings:call result:result]; } else if ([[call method] isEqualToString:@"loadUrl"]) { [self onLoadUrl:call result:result]; + } else if ([[call method] isEqualToString:@"loadAssetHtmlFile"]) { + [self onLoadAssetHtmlFile:call result:result]; + } else if ([[call method] isEqualToString:@"loadLocalHtmlFile"]) { + [self onLoadLocalHtmlFile:call result:result]; } else if ([[call method] isEqualToString:@"canGoBack"]) { [self onCanGoBack:call result:result]; } else if ([[call method] isEqualToString:@"canGoForward"]) { @@ -175,6 +183,28 @@ - (void)onLoadUrl:(FlutterMethodCall*)call result:(FlutterResult)result { } } +- (void)onLoadAssetHtmlFile:(FlutterMethodCall*)call result:(FlutterResult)result { + NSString* url = [call arguments]; + if (![self loadAssetHtmlFile:url]) { + result([FlutterError errorWithCode:@"loadAssetHtmlFile_failed" + message:@"Failed parsing the URL" + details:[NSString stringWithFormat:@"URL was: '%@'", url]]); + } else { + result(nil); + } +} + +- (void)onLoadLocalHtmlFile:(FlutterMethodCall*)call result:(FlutterResult)result { + NSString* url = [call arguments]; + if (![self loadLocalHtmlFile:url]) { + result([FlutterError errorWithCode:@"loadAssetHtmlFile_failed" + message:@"Failed parsing the URL" + details:[NSString stringWithFormat:@"URL was: '%@'", url]]); + } else { + result(nil); + } +} + - (void)onCanGoBack:(FlutterMethodCall*)call result:(FlutterResult)result { BOOL canGoBack = [_webView canGoBack]; result([NSNumber numberWithBool:canGoBack]); @@ -374,6 +404,58 @@ - (bool)loadUrl:(NSString*)url withHeaders:(NSDictionary*) return true; } +- (bool)loadAssetHtmlFile:(NSString*)url { + NSArray* array = [url componentsSeparatedByString:@"?"]; + NSString* pathString = [array objectAtIndex:0]; + NSLog(@"%@%@", @"pathString: ", pathString); + NSString* key = [_registrar lookupKeyForAsset:pathString]; + NSURL* baseURL = [[NSBundle mainBundle] URLForResource:key withExtension:nil]; + if (!baseURL) { + return false; + } + NSURL* newUrl = baseURL; + if ([array count] > 1) { + NSString* queryString = [array objectAtIndex:1]; + NSLog(@"%@%@", @"queryString: ", queryString); + NSString* queryPart = [NSString stringWithFormat:@"%@%@", @"?", queryString]; + NSLog(@"%@%@", @"queryPart: ", queryPart); + newUrl = [NSURL URLWithString:queryPart relativeToURL:baseURL]; + } + if (@available(iOS 9.0, *)) { + [_webView loadFileURL:newUrl allowingReadAccessToURL:[NSURL URLWithString:@"file:///"]]; + } else { + return false; + } + return true; +} + +- (bool)loadLocalHtmlFile:(NSString*)url { + NSArray* array = [url componentsSeparatedByString:@"?"]; + NSString* pathString = [array objectAtIndex:0]; + NSLog(@"%@%@", @"pathString: ", pathString); + NSString* key = [_registrar lookupKeyForAsset:pathString]; + NSURL* baseURL = [[NSBundle mainBundle] URLForResource:key withExtension:nil]; + if (!baseURL) { + [_webView loadFileURL:[NSURL fileURLWithPath:pathString] + allowingReadAccessToURL:[NSURL fileURLWithPath:pathString]]; + return true; + } + NSURL* newUrl = baseURL; + if ([array count] > 1) { + NSString* queryString = [array objectAtIndex:1]; + NSLog(@"%@%@", @"queryString: ", queryString); + NSString* queryPart = [NSString stringWithFormat:@"%@%@", @"?", queryString]; + NSLog(@"%@%@", @"queryPart: ", queryPart); + newUrl = [NSURL URLWithString:queryPart relativeToURL:baseURL]; + } + if (@available(iOS 9.0, *)) { + [_webView loadFileURL:newUrl allowingReadAccessToURL:[NSURL URLWithString:@"file:///"]]; + } else { + return false; + } + return true; +} + - (void)registerJavaScriptChannels:(NSSet*)channelNames controller:(WKUserContentController*)userContentController { for (NSString* channelName in channelNames) { diff --git a/packages/webview_flutter/lib/platform_interface.dart b/packages/webview_flutter/lib/platform_interface.dart index aaf63c24f08a..77b8cc54c6d8 100644 --- a/packages/webview_flutter/lib/platform_interface.dart +++ b/packages/webview_flutter/lib/platform_interface.dart @@ -64,6 +64,26 @@ abstract class WebViewPlatformController { "WebView loadUrl is not implemented on the current platform"); } + /// Load html file from local path + /// + /// `url` must not be null. + /// + /// Throws an ArgumentError if `url` is not a valid URL string. + Future loadAssetHtmlFile(String url) { + throw UnimplementedError( + "WebView loadAssetHtmlFile is not implemented on the current platform"); + } + + /// Load html file from local path + /// + /// `url` must not be null. + /// + /// Throws an ArgumentError if `url` is not a valid URL string. + Future loadLocalHtmlFile(String url) { + throw UnimplementedError( + "WebView loadLocalHtmlFile is not implemented on the current platform"); + } + /// Updates the webview settings. /// /// Any non null field in `settings` will be set as the new setting value. diff --git a/packages/webview_flutter/lib/src/webview_method_channel.dart b/packages/webview_flutter/lib/src/webview_method_channel.dart index 03d392ef5f8b..9011400d4275 100644 --- a/packages/webview_flutter/lib/src/webview_method_channel.dart +++ b/packages/webview_flutter/lib/src/webview_method_channel.dart @@ -60,6 +60,14 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { }); } + @override + Future loadAssetHtmlFile(String url) => + _channel.invokeMethod('loadAssetHtmlFile', url); + + @override + Future loadLocalHtmlFile(String url) => + _channel.invokeMethod('loadLocalHtmlFile', url); + @override Future currentUrl() => _channel.invokeMethod('currentUrl'); diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart index a91a9ac827ae..6a76ac2b0c07 100644 --- a/packages/webview_flutter/lib/webview_flutter.dart +++ b/packages/webview_flutter/lib/webview_flutter.dart @@ -531,6 +531,22 @@ class WebViewController { return _webViewPlatformController.loadUrl(url, headers); } + /// Load html file from assets + /// + /// `url` must not be null. + Future loadAssetHtmlFile(String url) async { + assert(url != null); + return _webViewPlatformController.loadAssetHtmlFile(url); + } + + /// Load html file from local path + /// + /// `url` must not be null. + Future loadLocalHtmlFile(String url) async { + assert(url != null); + return _webViewPlatformController.loadLocalHtmlFile(url); + } + /// Accessor to the current URL that the WebView is displaying. /// /// If [WebView.initialUrl] was never specified, returns `null`.